From 796c55419ab9b7c0a0c36c7a841b891e64ec2809 Mon Sep 17 00:00:00 2001 From: voluntas Date: Fri, 1 Mar 2024 18:19:31 +0900 Subject: [PATCH] =?UTF-8?q?examples=20=E3=81=AE=20class=20=E5=8C=96=20(#49?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * examples の class 化 * sendrecv を class 化する * id を remote-video にする * 大文字 * examples の simulcast を class 化 * コスメ * examples spotlight sendrecv の class 化 * channel_id の修正 * examples の spotlight sendonly / recvonly を class 化 * messaging を class に置き換える * github actions pnpm v3 に上げる * サンプルをclassベースに変更し、.env.templateを追加 * 送信まで * チェックまで実装してみる * page2 からもメッセージを送ってみる * waitForFunction 使ってみる * チェック以外を行う * skip にする * e2ee も class 化する --- .github/workflows/ci.yaml | 2 +- CHANGES.md | 9 +- examples/e2ee/index.html | 10 +- examples/e2ee/main.mjs | 88 ---------- examples/e2ee/main.mts | 167 ++++++++++++++++++ examples/messaging/index.html | 6 +- examples/messaging/main.mjs | 53 ------ examples/messaging/main.mts | 137 +++++++++++++++ examples/recvonly/index.html | 8 +- examples/recvonly/main.mjs | 55 ------ examples/recvonly/main.mts | 109 ++++++++++++ examples/sendonly/index.html | 11 +- examples/sendonly/main.mjs | 32 ---- examples/sendonly/main.mts | 85 ++++++++++ examples/sendrecv/index.html | 10 +- examples/sendrecv/main.mjs | 108 ------------ examples/sendrecv/main.mts | 142 ++++++++++++++++ examples/simulcast/index.html | 2 +- examples/simulcast/main.mjs | 110 ------------ examples/simulcast/main.mts | 198 ++++++++++++++++++++++ examples/spotlight_recvonly/index.html | 8 +- examples/spotlight_recvonly/main.mjs | 58 ------- examples/spotlight_recvonly/main.mts | 120 +++++++++++++ examples/spotlight_sendonly/index.html | 11 +- examples/spotlight_sendonly/main.mjs | 35 ---- examples/spotlight_sendonly/main.mts | 96 +++++++++++ examples/spotlight_sendrecv/index.html | 10 +- examples/spotlight_sendrecv/main.mjs | 107 ------------ examples/spotlight_sendrecv/main.mts | 148 ++++++++++++++++ examples/vite-env.d.ts | 11 ++ tests/messaging.spec.ts | 40 ++--- tests/sendonly_recvonly.spec.ts | 31 ++-- tests/sendrecv.spec.ts | 8 +- tests/spotlight_sendonly_recvonly.spec.ts | 28 +-- tests/spotlight_sendrecv.spec.ts | 8 +- tsconfig.json | 4 +- 36 files changed, 1318 insertions(+), 747 deletions(-) delete mode 100644 examples/e2ee/main.mjs create mode 100644 examples/e2ee/main.mts delete mode 100644 examples/messaging/main.mjs create mode 100644 examples/messaging/main.mts delete mode 100644 examples/recvonly/main.mjs create mode 100644 examples/recvonly/main.mts delete mode 100644 examples/sendonly/main.mjs create mode 100644 examples/sendonly/main.mts delete mode 100644 examples/sendrecv/main.mjs create mode 100644 examples/sendrecv/main.mts delete mode 100644 examples/simulcast/main.mjs create mode 100644 examples/simulcast/main.mts delete mode 100644 examples/spotlight_recvonly/main.mjs create mode 100644 examples/spotlight_recvonly/main.mts delete mode 100644 examples/spotlight_sendonly/main.mjs create mode 100644 examples/spotlight_sendonly/main.mts delete mode 100644 examples/spotlight_sendrecv/main.mjs create mode 100644 examples/spotlight_sendrecv/main.mts create mode 100644 examples/vite-env.d.ts diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d37107c1..ad4f6492 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v3 with: version: 8 - run: pnpm --version diff --git a/CHANGES.md b/CHANGES.md index c4e44803..30fd6c84 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,11 +14,6 @@ - [CHANGE] stopAudioTrack と stopVideoTrack を非推奨にする - 代わりに名前を変えただけの removeAudioTrack と removeVideoTrack を用意する - @voluntas - -## 2023.2.1 - -**テストとサンプルのみの変更であり、SDK の変更はありません** - - [CHANGE] examples を Vite を利用して動かすように変更する - serve を削除 - Vite を追加 @@ -27,6 +22,10 @@ - [CHANGE] deploy-pages.yml を削除する - E2E テストで実行できるようになったので - @voluntas +- [CHANGE] サンプルを class ベースに変更する + - @voluntas +- [ADD] サンプル用の .env.template を用意する + - @voluntas - [ADD] tests に Playwright を利用した E2E テストを追加する - e2ee と messaging は一旦 skip で追加 - @voluntas diff --git a/examples/e2ee/index.html b/examples/e2ee/index.html index b88a4a64..35d6d8ac 100644 --- a/examples/e2ee/index.html +++ b/examples/e2ee/index.html @@ -12,20 +12,20 @@

E2EE test

local

- -
+ +
-

remote

-
+
- + \ No newline at end of file diff --git a/examples/e2ee/main.mjs b/examples/e2ee/main.mjs deleted file mode 100644 index 6ccf00e8..00000000 --- a/examples/e2ee/main.mjs +++ /dev/null @@ -1,88 +0,0 @@ -import Sora from '../../dist/sora.mjs' - -const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL -const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' -const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' -const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' - -const debug = false -Sora.initE2EE('https://sora-e2ee-wasm.shiguredo.app/2020.2/wasm.wasm').catch((e) => { - document.querySelector('#error-message').textContent = - 'E2EE用 wasm ファイルの読み込みに失敗しました' -}) - -const sora = Sora.connection(SORA_SIGNALING_URL, debug) - -const channelId = `${SORA_CHANNEL_ID_PREFIX}e2ee${SORA_CHANNEL_ID_SUFFIX}` -const metadata = { access_token: ACCESS_TOKEN } -const options = { - e2ee: true, -} - -const sendrecv = sora.sendrecv(channelId, metadata, options) - -sendrecv.on('track', (event) => { - const stream = event.streams[0] - if (!stream) { - return - } - const remoteVideoBoxId = `remote-video-box-${stream.id}` - const remoteVideos = document.querySelector('#sendrecv-remote-videos') - if (!remoteVideos.querySelector(`#${remoteVideoBoxId}`)) { - const remoteVideoBox = document.createElement('div') - remoteVideoBox.id = remoteVideoBoxId - const connectionIdElement = document.createElement('div') - connectionIdElement.id = `${remoteVideoBoxId}-connection-id` - connectionIdElement.textContent = `connectionId: ${stream.id}` - remoteVideoBox.appendChild(connectionIdElement) - const fingerprintElement = document.createElement('div') - fingerprintElement.id = `${remoteVideoBoxId}-fingerprint` - remoteVideoBox.appendChild(fingerprintElement) - const remoteVideo = document.createElement('video') - remoteVideo.style.border = '1px solid red' - remoteVideo.autoplay = true - remoteVideo.playsinline = true - remoteVideo.controls = true - remoteVideo.srcObject = stream - remoteVideoBox.appendChild(remoteVideo) - remoteVideos.appendChild(remoteVideoBox) - } -}) -sendrecv.on('removetrack', (event) => { - const remoteVideo = document.querySelector(`#remote-video-box-${event.target.id}`) - if (remoteVideo) { - document.querySelector('#sendrecv-remote-videos').removeChild(remoteVideo) - } -}) -sendrecv.on('notify', (event) => { - console.log(event) - if (event.event_type === 'connection.created' && event.connection_id === sendrecv.connectionId) { - document.querySelector('#local-connection-id').textContent = `${sendrecv.connectionId}` - document.querySelector('#local-fingerprint').textContent = `${sendrecv.e2eeSelfFingerprint}` - } - - if (event.event_type === 'connection.created') { - const remoteFingerprints = sendrecv.e2eeRemoteFingerprints - // biome-ignore lint/complexity/noForEach: - Object.keys(remoteFingerprints).forEach((connectionId) => { - const fingerprintElement = document.querySelector( - `#remote-video-box-${connectionId}-fingerprint`, - ) - if (fingerprintElement) { - fingerprintElement.textContent = `fingerprint: ${remoteFingerprints[connectionId]}` - } - }) - } -}) - -document.querySelector('#start-sendrecv').addEventListener('click', async () => { - const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true }) - await sendrecv.connect(mediaStream) - document.querySelector('#sendrecv-local-video').srcObject = mediaStream -}) - -document.querySelector('#stop-sendrecv').addEventListener('click', async () => { - await sendrecv.disconnect() - document.querySelector('#sendrecv-local-video').srcObject = null - document.querySelector('#sendrecv-remote-videos').innerHTML = null -}) diff --git a/examples/e2ee/main.mts b/examples/e2ee/main.mts new file mode 100644 index 00000000..40aaabf8 --- /dev/null +++ b/examples/e2ee/main.mts @@ -0,0 +1,167 @@ +import Sora, { + type SoraConnection, + type SignalingNotifyMessage, + ConnectionPublisher, +} from '../../dist/sora' + +document.addEventListener('DOMContentLoaded', async () => { + const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL + const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' + const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' + const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' + + await Sora.initE2EE('https://sora-e2ee-wasm.shiguredo.app/2020.2/wasm.wasm').catch((e) => { + const errorMessageElement = document.querySelector('#error-message') + if (errorMessageElement) { + errorMessageElement.textContent = 'E2EE用 wasm ファイルの読み込みに失敗しました' + } + }) + + const client = new SoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + document.querySelector('#start')?.addEventListener('click', async () => { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) + await client.connect(stream) + }) + document.querySelector('#stop')?.addEventListener('click', async () => { + await client.disconnect() + }) +}) + +class SoraClient { + private debug = false + + private channelId: string + private metadata: { access_token: string } + private options: object + + private sora: SoraConnection + private connection: ConnectionPublisher + + constructor( + signalingUrl: string, + channelIdPrefix: string, + channelIdSuffix: string, + accessToken: string, + ) { + this.sora = Sora.connection(signalingUrl, this.debug) + this.channelId = `${channelIdPrefix}e2ee${channelIdSuffix}` + this.metadata = { access_token: accessToken } + this.options = { + e2ee: true, + } + + this.connection = this.sora.sendrecv(this.channelId, this.metadata, this.options) + + this.connection.on('notify', this.onnotify.bind(this)) + this.connection.on('track', this.ontrack.bind(this)) + this.connection.on('removetrack', this.onremovetrack.bind(this)) + } + + async connect(stream: MediaStream) { + await this.connection.connect(stream) + const localVideo = document.querySelector('#local-video') + if (localVideo) { + localVideo.srcObject = stream + } + } + + async disconnect() { + await this.connection.disconnect() + + // お掃除 + const localVideo = document.querySelector('#local-video') + if (localVideo) { + localVideo.srcObject = null + } + + const localConnectionId = document.querySelector('#local-connection-id') + if (localConnectionId) { + localConnectionId.textContent = '' + } + + const remoteVideos = document.querySelector('#remote-videos') + if (remoteVideos) { + remoteVideos.innerHTML = '' + } + } + + private onnotify(event: SignalingNotifyMessage): void { + if ( + event.event_type === 'connection.created' && + event.connection_id === this.connection.connectionId + ) { + const localConnectionId = document.querySelector('#local-connection-id') + if (localConnectionId) { + localConnectionId.textContent = this.connection.connectionId + } + + const localFingerprint = document.querySelector('#local-fingerprint') + if (localFingerprint) { + localFingerprint.textContent = this.connection.e2eeSelfFingerprint || null + } + } + + if (event.event_type === 'connection.created') { + const remoteFingerprints = this.connection.e2eeRemoteFingerprints || {} + Object.keys(remoteFingerprints).filter((connectionId) => { + const fingerprintElement = document.querySelector( + `#remote-video-box-${connectionId}-fingerprint`, + ) + if (fingerprintElement) { + fingerprintElement.textContent = `fingerprint: ${remoteFingerprints[connectionId]}` + } + }) + } + } + + private ontrack(event: RTCTrackEvent): void { + const stream = event.streams[0] + /* +
+
connectionId: ${stream.id} +
fingerprint: ${stream.id} + +
+ */ + + const remoteVideoBoxId = `remote-video-box-${stream.id}` + const remoteVideos = document.querySelector('#remote-videos') + if (remoteVideos && !remoteVideos.querySelector(`#${remoteVideoBoxId}`)) { + //
を作る + const remoteVideoBox = document.createElement('div') + remoteVideoBox.id = remoteVideoBoxId + //
を作る + const connectionIdElement = document.createElement('div') + connectionIdElement.id = `${remoteVideoBoxId}-connection-id` + connectionIdElement.textContent = `connectionId: ${stream.id}` + remoteVideoBox.appendChild(connectionIdElement) + //
を作る + const fingerprintElement = document.createElement('div') + fingerprintElement.id = `${remoteVideoBoxId}-fingerprint` + remoteVideoBox.appendChild(fingerprintElement) + //
- + \ No newline at end of file diff --git a/examples/simulcast/main.mjs b/examples/simulcast/main.mjs deleted file mode 100644 index c992a0f3..00000000 --- a/examples/simulcast/main.mjs +++ /dev/null @@ -1,110 +0,0 @@ -import Sora from '../../dist/sora.mjs' - -const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL -const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' -const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' -const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' - -const debug = false -const sora = Sora.connection(SORA_SIGNALING_URL, debug) - -const channelId = `${SORA_CHANNEL_ID_PREFIX}simulcast${SORA_CHANNEL_ID_SUFFIX}` -const metadata = { access_token: ACCESS_TOKEN } - -const sendonly = sora.sendonly(channelId, metadata, { - audio: false, - videoCodecType: 'VP8', - videoBitRate: 2500, - simulcast: true, -}) -sendonly.on('notify', (event) => { - console.log(event) - if (event.event_type === 'connection.created' && event.connection_id === sendonly.connectionId) { - document.querySelector('#local-video-connection-id').textContent = `${event.connection_id}` - } -}) - -const recvonlyR0 = sora.recvonly(channelId, metadata, { - simulcast: true, - simulcastRid: 'r0', -}) -recvonlyR0.on('notify', (event) => { - if ( - event.event_type === 'connection.created' && - event.connection_id === recvonlyR0.connectionId - ) { - console.log(`recvonly-r0: ${event.connection_id}`) - document.querySelector('#remote-video-connection-id-r0').textContent = `${event.connection_id}` - } -}) -recvonlyR0.on('track', (event) => { - document.querySelector('#remote-video-r0').srcObject = event.streams[0] -}) - -const recvonlyR1 = sora.recvonly(channelId, metadata, { - simulcast: true, - simulcastRid: 'r1', -}) -recvonlyR1.on('notify', (event) => { - if ( - event.event_type === 'connection.created' && - event.connection_id === recvonlyR1.connectionId - ) { - console.log(`recvonly-r1: ${event.connection_id}`) - document.querySelector('#remote-video-connection-id-r1').textContent = `${event.connection_id}` - } -}) -recvonlyR1.on('track', (event) => { - document.querySelector('#remote-video-r1').srcObject = event.streams[0] -}) - -const recvonlyR2 = sora.recvonly(channelId, metadata, { - simulcast: true, - simulcastRid: 'r2', -}) -recvonlyR2.on('notify', (event) => { - if ( - event.event_type === 'connection.created' && - event.connection_id === recvonlyR2.connectionId - ) { - console.log(`recvonly-r2: ${event.connection_id}`) - document.querySelector('#remote-video-connection-id-r2').textContent = `${event.connection_id}` - } -}) -recvonlyR2.on('track', (event) => { - document.querySelector('#remote-video-r2').srcObject = event.streams[0] -}) - -document.querySelector('#start').addEventListener('click', async () => { - // sendonly - const mediaStream = await navigator.mediaDevices.getUserMedia({ - audio: false, - video: { width: { exact: 1280 }, height: { exact: 720 } }, - }) - document.querySelector('#local-video').srcObject = mediaStream - await sendonly.connect(mediaStream) - - // recvonly r0 - await recvonlyR0.connect() - // recvonly r1 - await recvonlyR1.connect() - // recvonly r2 - await recvonlyR2.connect() -}) - -document.querySelector('#stop').addEventListener('click', async () => { - await sendonly.disconnect() - document.querySelector('#local-video').srcObject = null - - // recvonly r0 - await recvonlyR0.disconnect() - document.querySelector('#remote-video-r0').srcObject = null - - // recvonly r1 - await recvonlyR1.disconnect() - document.querySelector('#remote-video-r1').srcObject = null - - // recvonly r2 - await recvonlyR2.disconnect() - document.querySelector('#remote-video-r2').srcObject = null -}) diff --git a/examples/simulcast/main.mts b/examples/simulcast/main.mts new file mode 100644 index 00000000..0e217789 --- /dev/null +++ b/examples/simulcast/main.mts @@ -0,0 +1,198 @@ +import Sora, { + type SoraConnection, + type ConnectionPublisher, + type SignalingNotifyMessage, + ConnectionSubscriber, + SimulcastRid, +} from '../../dist/sora' + +document.addEventListener('DOMContentLoaded', () => { + const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL + const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' + const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' + const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' + + const sendonly = new SimulcastSendonlySoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + const recvonlyR0 = new SimulcastRecvonlySoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + 'r0', + ) + + const recvonlyR1 = new SimulcastRecvonlySoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + 'r1', + ) + + const recvonlyR2 = new SimulcastRecvonlySoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + 'r2', + ) + + document.querySelector('#start')?.addEventListener('click', async () => { + // sendonly + const stream = await navigator.mediaDevices.getUserMedia({ + audio: false, + video: { width: { exact: 1280 }, height: { exact: 720 } }, + }) + await sendonly.connect(stream) + + // recvonly r0 + await recvonlyR0.connect() + // recvonly r1 + await recvonlyR1.connect() + // recvonly r2 + await recvonlyR2.connect() + }) + + document.querySelector('#stop')?.addEventListener('click', async () => { + await sendonly.disconnect() + + // recvonly r0 + await recvonlyR0.disconnect() + // recvonly r1 + await recvonlyR1.disconnect() + // recvonly r2 + await recvonlyR2.disconnect() + }) +}) + +class SimulcastSendonlySoraClient { + private debug = false + private channelId: string + + private sora: SoraConnection + private connection: ConnectionPublisher + + constructor( + signaling_url: string, + channel_id_prefix: string, + channel_id_suffix: string, + access_token: string, + ) { + this.channelId = `${channel_id_prefix}simulcast${channel_id_suffix}` + + this.sora = Sora.connection(signaling_url, this.debug) + this.connection = this.sora.sendonly( + this.channelId, + { access_token }, + { audio: false, video: true, videoCodecType: 'VP8', videoBitRate: 2500, simulcast: true }, + ) + + this.connection.on('notify', this.onnotify.bind(this)) + } + + async connect(stream: MediaStream) { + await this.connection.connect(stream) + const localVideo = document.querySelector('#local-video') + if (localVideo) { + localVideo.srcObject = stream + } + } + + async disconnect() { + await this.connection.disconnect() + const localVideo = document.querySelector('#local-video') + if (localVideo) { + localVideo.srcObject = null + } + } + + private onnotify(event: SignalingNotifyMessage) { + if ( + event.event_type === 'connection.created' && + event.connection_id === this.connection.connectionId + ) { + const localVideoConnectionId = document.querySelector('#local-video-connection-id') + if (localVideoConnectionId) { + localVideoConnectionId.textContent = `${event.connection_id}` + } + } + } +} + +class SimulcastRecvonlySoraClient { + private debug = false + + private channelId: string + private rid: SimulcastRid + + private sora: SoraConnection + private connection: ConnectionSubscriber + + constructor( + signaling_url: string, + channel_id_prefix: string, + channel_id_suffix: string, + access_token: string, + rid: SimulcastRid, + ) { + this.channelId = `${channel_id_prefix}simulcast${channel_id_suffix}` + this.rid = rid + + this.sora = Sora.connection(signaling_url, this.debug) + this.connection = this.sora.recvonly( + this.channelId, + { access_token }, + { simulcastRid: this.rid, simulcast: true }, + ) + + this.connection.on('notify', this.onnotify.bind(this)) + this.connection.on('track', this.ontrack.bind(this)) + this.connection.on('removetrack', this.onremovetrack.bind(this)) + } + + async connect() { + await this.connection.connect() + } + + async disconnect() { + await this.connection.disconnect() + const remoteVideo = document.querySelector(`#remote-video-${this.rid}`) + if (remoteVideo) { + remoteVideo.srcObject = null + } + } + + private onnotify(event: SignalingNotifyMessage) { + if ( + event.event_type === 'connection.created' && + event.connection_id === this.connection.connectionId + ) { + const localVideoConnectionId = document.querySelector( + `#remote-video-connection-id-${this.rid}`, + ) + if (localVideoConnectionId) { + localVideoConnectionId.textContent = `${event.connection_id}` + } + } + } + + private ontrack(event: RTCTrackEvent) { + const remoteVideo = document.querySelector(`#remote-video-${this.rid}`) + if (remoteVideo) { + remoteVideo.srcObject = event.streams[0] + } + } + + private onremovetrack(event: MediaStreamTrackEvent) { + const remoteVideo = document.querySelector(`#remote-video-${this.rid}`) + if (remoteVideo) { + remoteVideo.srcObject = null + } + } +} diff --git a/examples/spotlight_recvonly/index.html b/examples/spotlight_recvonly/index.html index f4153b6c..d6da3bd6 100644 --- a/examples/spotlight_recvonly/index.html +++ b/examples/spotlight_recvonly/index.html @@ -8,15 +8,15 @@

Spotlight Recvonly test

- -
-
+ +
+
- + \ No newline at end of file diff --git a/examples/spotlight_recvonly/main.mjs b/examples/spotlight_recvonly/main.mjs deleted file mode 100644 index d2be592b..00000000 --- a/examples/spotlight_recvonly/main.mjs +++ /dev/null @@ -1,58 +0,0 @@ -import Sora from '../../dist/sora.mjs' - -const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL -const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' -const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' -const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' - -const channelId = `${SORA_CHANNEL_ID_PREFIX}spotlight_sendonly_recvonly${SORA_CHANNEL_ID_SUFFIX}` -const debug = false -const sora = Sora.connection(SORA_SIGNALING_URL, debug) -const metadata = { access_token: ACCESS_TOKEN } -const options = { - multistream: true, - simulcast: true, - spotlight: true, -} -const recvonly = sora.recvonly(channelId, metadata, options) - -recvonly.on('notify', (event) => { - if (event.event_type === 'connection.created' && recvonly.connectionId === event.connection_id) { - const connectionIdElement = document.querySelector('#recvonly-connection-id') - connectionIdElement.textContent = event.connection_id - } -}) - -recvonly.on('track', (event) => { - const stream = event.streams[0] - if (!stream) return - const remoteVideoId = `remotevideo-${stream.id}` - const remoteVideos = document.querySelector('#remote-videos') - if (!remoteVideos.querySelector(`#${remoteVideoId}`)) { - const remoteVideo = document.createElement('video') - remoteVideo.id = remoteVideoId - remoteVideo.style.border = '1px solid red' - remoteVideo.autoplay = true - remoteVideo.playsinline = true - remoteVideo.controls = true - remoteVideo.srcObject = stream - remoteVideos.appendChild(remoteVideo) - } -}) - -recvonly.on('removetrack', (event) => { - const remoteVideo = document.querySelector(`#remotevideo-${event.target.id}`) - if (remoteVideo) { - remoteVideo.srcObject = null - document.querySelector('#remote-videos').removeChild(remoteVideo) - } -}) - -document.querySelector('#start-recvonly').addEventListener('click', async () => { - await recvonly.connect() -}) - -document.querySelector('#stop-recvonly').addEventListener('click', async () => { - await recvonly.disconnect() - document.querySelector('#remote-videos').innerHTML = null -}) diff --git a/examples/spotlight_recvonly/main.mts b/examples/spotlight_recvonly/main.mts new file mode 100644 index 00000000..47264399 --- /dev/null +++ b/examples/spotlight_recvonly/main.mts @@ -0,0 +1,120 @@ +import Sora, { + type SoraConnection, + type SignalingNotifyMessage, + type ConnectionSubscriber, +} from '../../dist/sora' + +document.addEventListener('DOMContentLoaded', () => { + // 環境変数の読み込み + const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL + const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' + const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' + const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' + + // Sora クライアントの初期化 + const client = new SoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + document.querySelector('#start')?.addEventListener('click', async () => { + await client.connect() + }) + + document.querySelector('#stop')?.addEventListener('click', async () => { + await client.disconnect() + }) +}) + +class SoraClient { + private debug = false + private channelId: string + private metadata: { access_token: string } + private options: object = {} + + private sora: SoraConnection + private connection: ConnectionSubscriber + + constructor( + signaling_url: string, + channel_id_prefix: string, + channel_id_suffix: string, + access_token: string, + ) { + this.sora = Sora.connection(signaling_url, this.debug) + + this.options = { + multistream: true, + simulcast: true, + spotlight: true, + } + + // channel_id の生成 + this.channelId = `${channel_id_prefix}spotlight_sendonly_recvonly${channel_id_suffix}` + // access_token を指定する metadata の生成 + this.metadata = { access_token: access_token } + + this.connection = this.sora.recvonly(this.channelId, this.metadata, this.options) + this.connection.on('notify', this.onnotify.bind(this)) + this.connection.on('track', this.ontrack.bind(this)) + this.connection.on('removetrack', this.onremovetrack.bind(this)) + } + + async connect(): Promise { + await this.connection.connect() + } + + async disconnect(): Promise { + await this.connection.disconnect() + const remoteVideos = document.querySelector('#remote-videos') + if (remoteVideos) { + remoteVideos.innerHTML = '' + } + + const connectionIdElement = document.querySelector('#connection-id') + if (connectionIdElement) { + connectionIdElement.textContent = null + } + } + + private onnotify(event: SignalingNotifyMessage) { + // 自分の connection_id を取得する + if ( + event.event_type === 'connection.created' && + this.connection.connectionId === event.connection_id + ) { + const connectionIdElement = document.querySelector('#connection-id') + if (connectionIdElement) { + connectionIdElement.textContent = event.connection_id + } + } + } + + private ontrack(event: RTCTrackEvent) { + // Sora の場合、event.streams には MediaStream が 1 つだけ含まれる + const stream = event.streams[0] + const remoteVideoId = `remotevideo-${stream.id}` + const remoteVideos = document.querySelector('#remote-videos') + if (remoteVideos && !remoteVideos.querySelector(`#${remoteVideoId}`)) { + const remoteVideo = document.createElement('video') + remoteVideo.id = remoteVideoId + remoteVideo.style.border = '1px solid red' + remoteVideo.autoplay = true + remoteVideo.playsInline = true + remoteVideo.controls = true + remoteVideo.srcObject = stream + remoteVideos.appendChild(remoteVideo) + } + } + + private onremovetrack(event: MediaStreamTrackEvent) { + // このトラックが属している MediaStream の id を取得する + const stream = event.target as MediaStream + const remoteVideo = document.querySelector(`#remotevideo-${stream.id}`) + if (remoteVideo) { + document.querySelector('#remote-videos')?.removeChild(remoteVideo) + } + } +} diff --git a/examples/spotlight_sendonly/index.html b/examples/spotlight_sendonly/index.html index 299f9db0..6e0ecc41 100644 --- a/examples/spotlight_sendonly/index.html +++ b/examples/spotlight_sendonly/index.html @@ -8,14 +8,15 @@

Spotlight Sendonly test

- -
-
- + + \ No newline at end of file diff --git a/examples/spotlight_sendonly/main.mjs b/examples/spotlight_sendonly/main.mjs deleted file mode 100644 index 09134ef9..00000000 --- a/examples/spotlight_sendonly/main.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import Sora from '../../dist/sora.mjs' - -const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL -const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' -const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' -const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' - -const channelId = `${SORA_CHANNEL_ID_PREFIX}spotlight_sendonly_recvonly${SORA_CHANNEL_ID_SUFFIX}` -const debug = false -const sora = Sora.connection(SORA_SIGNALING_URL, debug) -const metadata = { access_token: ACCESS_TOKEN } -const options = { - multistream: true, - simulcast: true, - spotlight: true, -} -const sendonly = sora.sendonly(channelId, metadata, options) - -sendonly.on('notify', (event) => { - if (event.event_type === 'connection.created' && sendonly.connectionId === event.connection_id) { - const connectionIdElement = document.querySelector('#sendonly-connection-id') - connectionIdElement.textContent = event.connection_id - } -}) - -document.querySelector('#start-sendonly').addEventListener('click', async () => { - const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) - document.querySelector('#sendonly-local-video').srcObject = mediaStream - await sendonly.connect(mediaStream) -}) - -document.querySelector('#stop-sendonly').addEventListener('click', async () => { - await sendonly.disconnect() - document.querySelector('#sendonly-local-video').srcObject = null -}) diff --git a/examples/spotlight_sendonly/main.mts b/examples/spotlight_sendonly/main.mts new file mode 100644 index 00000000..bf4c955f --- /dev/null +++ b/examples/spotlight_sendonly/main.mts @@ -0,0 +1,96 @@ +import Sora, { + type SignalingNotifyMessage, + type ConnectionPublisher, + type SoraConnection, +} from '../../dist/sora' + +document.addEventListener('DOMContentLoaded', async () => { + const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL + const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' + const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' + const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' + + const client = new SoraClient( + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + document.querySelector('#start')?.addEventListener('click', async () => { + const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }) + await client.connect(stream) + }) + + document.querySelector('#stop')?.addEventListener('click', async () => { + await client.disconnect() + }) +}) + +class SoraClient { + private debug = false + private channelId: string + private metadata: { access_token: string } + private options: object = {} + + private sora: SoraConnection + private connection: ConnectionPublisher + + constructor( + signaling_url: string, + channel_id_prefix: string, + channel_id_suffix: string, + access_token: string, + ) { + this.sora = Sora.connection(signaling_url, this.debug) + + this.options = { + multistream: true, + simulcast: true, + spotlight: true, + } + + // channel_id の生成 + this.channelId = `${channel_id_prefix}spotlight_sendonly_recvonly${channel_id_suffix}` + // access_token を指定する metadata の生成 + this.metadata = { access_token: access_token } + + this.connection = this.sora.sendonly(this.channelId, this.metadata, this.options) + this.connection.on('notify', this.onnotify.bind(this)) + } + + async connect(stream: MediaStream): Promise { + await this.connection.connect(stream) + + const videoElement = document.querySelector('#local-video') + if (videoElement !== null) { + videoElement.srcObject = stream + } + } + + async disconnect(): Promise { + await this.connection.disconnect() + + const videoElement = document.querySelector('#local-video') + if (videoElement !== null) { + videoElement.srcObject = null + } + + const connectionIdElement = document.querySelector('#connection-id') + if (connectionIdElement) { + connectionIdElement.textContent = null + } + } + + private onnotify(event: SignalingNotifyMessage): void { + if ( + event.event_type === 'connection.created' && + this.connection.connectionId === event.connection_id + ) { + const connectionIdElement = document.querySelector('#connection-id') + if (connectionIdElement) { + connectionIdElement.textContent = event.connection_id + } + } + } +} diff --git a/examples/spotlight_sendrecv/index.html b/examples/spotlight_sendrecv/index.html index d8e8a82a..8378c140 100644 --- a/examples/spotlight_sendrecv/index.html +++ b/examples/spotlight_sendrecv/index.html @@ -11,8 +11,8 @@

Spotlight Sendrecv test

sendrecv1

- -
+ +
@@ -20,8 +20,8 @@

sendrecv1

sendrecv2

- -
+ +
@@ -30,7 +30,7 @@

sendrecv2

- + \ No newline at end of file diff --git a/examples/spotlight_sendrecv/main.mjs b/examples/spotlight_sendrecv/main.mjs deleted file mode 100644 index 7989e281..00000000 --- a/examples/spotlight_sendrecv/main.mjs +++ /dev/null @@ -1,107 +0,0 @@ -import Sora from '../../dist/sora.mjs' - -const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL -const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' -const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' -const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' - -const channelId = `${SORA_CHANNEL_ID_PREFIX}spotlight${SORA_CHANNEL_ID_SUFFIX}` -const debug = false -const sora = Sora.connection(SORA_SIGNALING_URL, debug) -const metadata = { access_token: ACCESS_TOKEN } -const options = { - audio: true, - video: true, - simulcast: true, - spotlight: true, - spotlightNumber: 1, -} - -const sendrecv1 = sora.sendrecv(channelId, metadata, options) - -sendrecv1.on('notify', (event) => { - if (event.event_type === 'connection.created' && sendrecv1.connectionId === event.connection_id) { - const connectionIdElement = document.querySelector('#sendrecv1-connection-id') - connectionIdElement.textContent = event.connection_id - } -}) - -sendrecv1.on('track', (event) => { - const stream = event.streams[0] - if (!stream) return - const remoteVideoId = `sendrecv1-remotevideo-${stream.id}` - const remoteVideos = document.querySelector('#sendrecv1-remote-videos') - if (!remoteVideos.querySelector(`#${remoteVideoId}`)) { - const remoteVideo = document.createElement('video') - remoteVideo.id = remoteVideoId - remoteVideo.style.border = '1px solid red' - remoteVideo.autoplay = true - remoteVideo.playsinline = true - remoteVideo.controls = true - remoteVideo.srcObject = stream - remoteVideos.appendChild(remoteVideo) - } -}) - -sendrecv1.on('removetrack', (event) => { - const remoteVideo = document.querySelector(`#sendrecv1-remotevideo-${event.target.id}`) - if (remoteVideo) { - document.querySelector('#sendrecv1-remote-videos').removeChild(remoteVideo) - } -}) - -const sendrecv2 = sora.sendrecv(channelId, metadata, options) -sendrecv2.on('notify', (event) => { - if (event.event_type === 'connection.created' && sendrecv2.connectionId === event.connection_id) { - const connectionIdElement = document.querySelector('#sendrecv2-connection-id') - connectionIdElement.textContent = event.connection_id - } -}) - -sendrecv2.on('track', (event) => { - const stream = event.streams[0] - if (!stream) return - const remoteVideoId = `sendrecv2-remotevideo-${stream.id}` - const remoteVideos = document.querySelector('#sendrecv2-remote-videos') - if (!remoteVideos.querySelector(`#${remoteVideoId}`)) { - const remoteVideo = document.createElement('video') - remoteVideo.id = remoteVideoId - remoteVideo.style.border = '1px solid red' - remoteVideo.autoplay = true - remoteVideo.playsinline = true - remoteVideo.controls = true - remoteVideo.srcObject = stream - remoteVideos.appendChild(remoteVideo) - } -}) -sendrecv2.on('removetrack', (event) => { - const remoteVideo = document.querySelector(`#sendrecv2-remotevideo-${event.target.id}`) - if (remoteVideo) { - remoteVideo.srcObject = null - document.querySelector('#sendrecv2-remote-videos').removeChild(remoteVideo) - } -}) - -document.querySelector('#start-sendrecv1').addEventListener('click', async () => { - // sendrecv1 - const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) - - document.querySelector('#sendrecv1-local-video').srcObject = mediaStream - await sendrecv1.connect(mediaStream) -}) -document.querySelector('#start-sendrecv2').addEventListener('click', async () => { - // sendrecv2 - const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) - document.querySelector('#sendrecv2-local-video').srcObject = mediaStream - await sendrecv2.connect(mediaStream) -}) -document.querySelector('#stop-sendrecv1').addEventListener('click', async () => { - await sendrecv1.disconnect() - document.querySelector('#sendrecv1-local-video').srcObject = null - document.querySelector('#sendrecv1-remote-videos').innerHTML = null -}) -document.querySelector('#stop-sendrecv2').addEventListener('click', async () => { - sendrecv2.disconnect() - document.querySelector('#sendrecv2-local-video').srcObject = null - document.querySelector('#sendrecv2-remote-videos').innerHTML = null -}) diff --git a/examples/spotlight_sendrecv/main.mts b/examples/spotlight_sendrecv/main.mts new file mode 100644 index 00000000..b4ff81f7 --- /dev/null +++ b/examples/spotlight_sendrecv/main.mts @@ -0,0 +1,148 @@ +import Sora, { + type SoraConnection, + type ConnectionPublisher, + type SignalingNotifyMessage, +} from '../../dist/sora' + +document.addEventListener('DOMContentLoaded', async () => { + const SORA_SIGNALING_URL = import.meta.env.VITE_SORA_SIGNALING_URL + const SORA_CHANNEL_ID_PREFIX = import.meta.env.VITE_SORA_CHANNEL_ID_PREFIX || '' + const SORA_CHANNEL_ID_SUFFIX = import.meta.env.VITE_SORA_CHANNEL_ID_SUFFIX || '' + const ACCESS_TOKEN = import.meta.env.VITE_ACCESS_TOKEN || '' + + const sendrecv1 = new SoraClient( + 'sendrecv1', + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + const sendrecv2 = new SoraClient( + 'sendrecv2', + SORA_SIGNALING_URL, + SORA_CHANNEL_ID_PREFIX, + SORA_CHANNEL_ID_SUFFIX, + ACCESS_TOKEN, + ) + + document.querySelector('#sendrecv1-start')?.addEventListener('click', async () => { + // sendrecv1 + const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) + await sendrecv1.connect(stream) + }) + document.querySelector('#sendrecv1-stop')?.addEventListener('click', async () => { + await sendrecv1.disconnect() + }) + + document.querySelector('#sendrecv2-start')?.addEventListener('click', async () => { + // sendrecv2 + const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) + await sendrecv2.connect(stream) + }) + document.querySelector('#sendrecv2-stop')?.addEventListener('click', async () => { + await sendrecv2.disconnect() + }) +}) + +class SoraClient { + // sendrecv1 or sendrecv2 + private label: string + + private debug = false + + private channelId: string + private metadata: { access_token: string } + private options: object + + private sora: SoraConnection + private connection: ConnectionPublisher + + constructor( + label: string, + signalingUrl: string, + channelIdPrefix: string, + channelIdSuffix: string, + accessToken: string, + ) { + this.label = label + + this.sora = Sora.connection(signalingUrl, this.debug) + this.channelId = `${channelIdPrefix}spotlight_sendrecv${channelIdSuffix}` + this.metadata = { access_token: accessToken } + this.options = { + audio: true, + video: true, + simulcast: true, + spotlight: true, + spotlightNumber: 1, + } + + this.connection = this.sora.sendrecv(this.channelId, this.metadata, this.options) + + this.connection.on('notify', this.onnotify.bind(this)) + this.connection.on('track', this.ontrack.bind(this)) + this.connection.on('removetrack', this.onremovetrack.bind(this)) + } + + async connect(stream: MediaStream) { + await this.connection.connect(stream) + const localVideo = document.querySelector(`#${this.label}-local-video`) + if (localVideo) { + localVideo.srcObject = stream + } + } + + async disconnect() { + await this.connection.disconnect() + + // お掃除 + const localVideo = document.querySelector(`#${this.label}-local-video`) + if (localVideo) { + localVideo.srcObject = null + } + // お掃除 + const remoteVideos = document.querySelector(`#${this.label}-remote-videos`) + if (remoteVideos) { + remoteVideos.innerHTML = '' + } + } + + private onnotify(event: SignalingNotifyMessage): void { + if ( + event.event_type === 'connection.created' && + this.connection.connectionId === event.connection_id + ) { + const connectionIdElement = document.querySelector(`#${this.label}-connection-id`) + if (connectionIdElement) { + connectionIdElement.textContent = event.connection_id + } + } + } + + private ontrack(event: RTCTrackEvent): void { + const stream = event.streams[0] + const remoteVideoId = `${this.label}-remote-video-${stream.id}` + const remoteVideos = document.querySelector(`#${this.label}-remote-videos`) + if (remoteVideos && !remoteVideos.querySelector(`#${remoteVideoId}`)) { + const remoteVideo = document.createElement('video') + remoteVideo.id = remoteVideoId + remoteVideo.style.border = '1px solid red' + remoteVideo.autoplay = true + remoteVideo.playsInline = true + remoteVideo.controls = true + remoteVideo.width = 160 + remoteVideo.height = 120 + remoteVideo.srcObject = stream + remoteVideos.appendChild(remoteVideo) + } + } + + private onremovetrack(event: MediaStreamTrackEvent): void { + const target = event.target as MediaStream + const remoteVideo = document.querySelector(`#${this.label}-remote-video-${target.id}`) + if (remoteVideo) { + document.querySelector(`#${this.label}-remote-videos`)?.removeChild(remoteVideo) + } + } +} diff --git a/examples/vite-env.d.ts b/examples/vite-env.d.ts new file mode 100644 index 00000000..9fa69035 --- /dev/null +++ b/examples/vite-env.d.ts @@ -0,0 +1,11 @@ +/// + +interface ImportMetaEnv { + VITE_SORA_SIGNALING_URL: string + VITE_SORA_CHANNEL_ID: string + VITE_ACCESS_TOKEN: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/tests/messaging.spec.ts b/tests/messaging.spec.ts index a4455161..db1e9876 100644 --- a/tests/messaging.spec.ts +++ b/tests/messaging.spec.ts @@ -12,37 +12,39 @@ test.skip('messaging pages', async ({ browser }) => { await page1.click('#start') await page2.click('#start') - await page1.waitForSelector('#local-connection-id:not(:empty)') - const page1ConnectionId = await page1.$eval('#local-connection-id', (el) => el.textContent) + await page1.waitForSelector('#connection-id:not(:empty)') + const page1ConnectionId = await page1.$eval('#connection-id', (el) => el.textContent) console.log(`page1 connectionId=${page1ConnectionId}`) - await page2.waitForSelector('#local-connection-id:not(:empty)') - const page2ConnectionId = await page2.$eval('#local-connection-id', (el) => el.textContent) + await page2.waitForSelector('#connection-id:not(:empty)') + const page2ConnectionId = await page2.$eval('#connection-id', (el) => el.textContent) console.log(`page2 connectionId=${page2ConnectionId}`) // page1からpage2へメッセージを送信 - await page1.fill('input[name="message"]', 'Hello from page1') + const page1Message = 'Hello from page1' + await page1.fill('input[name="message"]', page1Message) await page1.click('#send-message') // page2でメッセージが受信されたことを確認 - await page2.waitForSelector('#received-messages li', { state: 'attached' }) - const receivedMessage1 = await page2.$eval('#received-messages li', (el) => el.textContent) + // await page2.waitForSelector('#received-messages li', { state: 'attached' }) + // const receivedMessage1 = await page2.$eval('#received-messages li', (el) => el.textContent) - // 受信したメッセージが期待したものであるか検証 - console.log(`Received message on page2: ${receivedMessage1}`) - test.expect(receivedMessage1).toBe('Hello from page1') + // // 受信したメッセージが期待したものであるか検証 + // console.log(`Received message on page2: ${receivedMessage1}`) + // test.expect(receivedMessage1).toBe(page1Message) - // page2からpage1へメッセージを送信 - await page2.fill('input[name="message"]', 'Hello from page2') - await page2.click('#send-message') + // // page2からpage1へメッセージを送信 + // const page2Message = 'Hello from page2' + // await page2.fill('input[name="message"]', page2Message) + // await page2.click('#send-message') - // page1でメッセージが受信されたことを確認 - await page1.waitForSelector('li', { state: 'attached' }) - const receivedMessage2 = await page1.$eval('#received-messages li', (el) => el.textContent) + // // page1でメッセージが受信されたことを確認 + // await page1.waitForSelector('li', { state: 'attached' }) + // const receivedMessage2 = await page1.$eval('#received-messages li', (el) => el.textContent) - // 受信したメッセージが期待したものであるか検証 - console.log(`Received message on page1: ${receivedMessage2}`) - test.expect(receivedMessage2).toBe('Hello from page2') + // // 受信したメッセージが期待したものであるか検証 + // console.log(`Received message on page1: ${receivedMessage2}`) + // test.expect(receivedMessage2).toBe(page2Message) await page1.click('#stop') await page2.click('#stop') diff --git a/tests/sendonly_recvonly.spec.ts b/tests/sendonly_recvonly.spec.ts index a9dfc32e..30e45373 100644 --- a/tests/sendonly_recvonly.spec.ts +++ b/tests/sendonly_recvonly.spec.ts @@ -2,33 +2,36 @@ import { test } from '@playwright/test' test('sendonly/recvonly pages', async ({ browser }) => { // 新しいページを2つ作成 - const page1 = await browser.newPage() - const page2 = await browser.newPage() + const sendonly = await browser.newPage() + const recvonly = await browser.newPage() // それぞれのページに対して操作を行う - await page1.goto('http://localhost:9000/sendonly/') - await page2.goto('http://localhost:9000/recvonly/') + await sendonly.goto('http://localhost:9000/sendonly/') + await recvonly.goto('http://localhost:9000/recvonly/') - await page1.click('#start-sendonly') - await page2.click('#start-recvonly') + await sendonly.click('#start') + await recvonly.click('#start') // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ - await page1.waitForSelector('#sendonly-connection-id:not(:empty)') + await sendonly.waitForSelector('#connection-id:not(:empty)') // #sendonly-connection-id 要素の内容を取得 - const sendonlyConnectionId = await page1.$eval('#sendonly-connection-id', (el) => el.textContent) + const sendonlyConnectionId = await sendonly.$eval('#connection-id', (el) => el.textContent) console.log(`sendonly connectionId=${sendonlyConnectionId}`) // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ - await page2.waitForSelector('#recvonly-connection-id:not(:empty)') + await recvonly.waitForSelector('#connection-id:not(:empty)') // #sendrecv1-connection-id 要素の内容を取得 - const recvonlyConnectionId = await page2.$eval('#recvonly-connection-id', (el) => el.textContent) + const recvonlyConnectionId = await recvonly.$eval( + '#connection-id', + (el) => el.textContent, + ) console.log(`recvonly connectionId=${recvonlyConnectionId}`) - await page1.click('#stop-sendonly') - await page2.click('#stop-recvonly') + await sendonly.click('#stop') + await recvonly.click('#stop') - await page1.close() - await page2.close() + await sendonly.close() + await recvonly.close() }) diff --git a/tests/sendrecv.spec.ts b/tests/sendrecv.spec.ts index 1116ebd3..d8e62447 100644 --- a/tests/sendrecv.spec.ts +++ b/tests/sendrecv.spec.ts @@ -3,8 +3,8 @@ import { test } from '@playwright/test' test('sendrecv x2', async ({ page }) => { await page.goto('http://localhost:9000/sendrecv/') - await page.click('#start-sendrecv1') - await page.click('#start-sendrecv2') + await page.click('#sendrecv1-start') + await page.click('#sendrecv2-start') // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ await page.waitForSelector('#sendrecv1-connection-id:not(:empty)') @@ -20,6 +20,6 @@ test('sendrecv x2', async ({ page }) => { const sendrecv2ConnectionId = await page.$eval('#sendrecv2-connection-id', (el) => el.textContent) console.log(`sendrecv2 connectionId=${sendrecv2ConnectionId}`) - await page.click('#stop-sendrecv1') - await page.click('#stop-sendrecv2') + await page.click('#sendrecv1-stop') + await page.click('#sendrecv2-stop') }) diff --git a/tests/spotlight_sendonly_recvonly.spec.ts b/tests/spotlight_sendonly_recvonly.spec.ts index e480260b..ca9c3851 100644 --- a/tests/spotlight_sendonly_recvonly.spec.ts +++ b/tests/spotlight_sendonly_recvonly.spec.ts @@ -2,33 +2,33 @@ import { test } from '@playwright/test' test('spotlight sendonly/recvonly pages', async ({ browser }) => { // 新しいページを2つ作成 - const page1 = await browser.newPage() - const page2 = await browser.newPage() + const sendonly = await browser.newPage() + const recvonly = await browser.newPage() // それぞれのページに対して操作を行う - await page1.goto('http://localhost:9000/spotlight_sendonly/') - await page2.goto('http://localhost:9000/spotlight_recvonly/') + await sendonly.goto('http://localhost:9000/spotlight_sendonly/') + await recvonly.goto('http://localhost:9000/spotlight_recvonly/') - await page1.click('#start-sendonly') - await page2.click('#start-recvonly') + await sendonly.click('#start') + await recvonly.click('#start') // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ - await page1.waitForSelector('#sendonly-connection-id:not(:empty)') + await sendonly.waitForSelector('#connection-id:not(:empty)') // #sendonly-connection-id 要素の内容を取得 - const sendonlyConnectionId = await page1.$eval('#sendonly-connection-id', (el) => el.textContent) + const sendonlyConnectionId = await sendonly.$eval('#connection-id', (el) => el.textContent) console.log(`sendonly connectionId=${sendonlyConnectionId}`) // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ - await page2.waitForSelector('#recvonly-connection-id:not(:empty)') + await recvonly.waitForSelector('#connection-id:not(:empty)') // #sendrecv1-connection-id 要素の内容を取得 - const recvonlyConnectionId = await page2.$eval('#recvonly-connection-id', (el) => el.textContent) + const recvonlyConnectionId = await recvonly.$eval('#connection-id', (el) => el.textContent) console.log(`recvonly connectionId=${recvonlyConnectionId}`) - await page1.click('#stop-sendonly') - await page2.click('#stop-recvonly') + await sendonly.click('#stop') + await recvonly.click('#stop') - await page1.close() - await page2.close() + await sendonly.close() + await recvonly.close() }) diff --git a/tests/spotlight_sendrecv.spec.ts b/tests/spotlight_sendrecv.spec.ts index e002a38f..ad7e5470 100644 --- a/tests/spotlight_sendrecv.spec.ts +++ b/tests/spotlight_sendrecv.spec.ts @@ -3,8 +3,8 @@ import { test } from '@playwright/test' test('spotlight sendrecv x2', async ({ page }) => { await page.goto('http://localhost:9000/spotlight_sendrecv/') - await page.click('#start-sendrecv1') - await page.click('#start-sendrecv2') + await page.click('#sendrecv1-start') + await page.click('#sendrecv2-start') // #sendrecv1-connection-id 要素が存在し、その内容が空でないことを確認するまで待つ await page.waitForSelector('#sendrecv1-connection-id:not(:empty)') @@ -20,6 +20,6 @@ test('spotlight sendrecv x2', async ({ page }) => { const sendrecv2ConnectionId = await page.$eval('#sendrecv2-connection-id', (el) => el.textContent) console.log(`sendrecv2 connectionId=${sendrecv2ConnectionId}`) - await page.click('#stop-sendrecv1') - await page.click('#stop-sendrecv2') + await page.click('#sendrecv1-stop') + await page.click('#sendrecv2-stop') }) diff --git a/tsconfig.json b/tsconfig.json index cb99bb53..dc0d54bb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "target": "es2020", - "module": "es2020", + "target": "ES2020", + "module": "ES2020", "strict": true, "declaration": true, "strictNullChecks": true,