Skip to content

Commit

Permalink
feat: video props and props validations
Browse files Browse the repository at this point in the history
  • Loading branch information
carlossantos74 committed Jan 24, 2025
1 parent e0e3818 commit a8f8cd5
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 8 deletions.
9 changes: 9 additions & 0 deletions packages/video/src/common/types/brand.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { z } from 'zod';

export const BrandSchema = z.object({
logoUrl: z.string().url('[SuperViz] - logoUrl must be a valid URL').optional(),
});

export type Brand = {
logoUrl?: string;
}
28 changes: 28 additions & 0 deletions packages/video/src/common/types/participant.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export interface Avatar {
model3DUrl?: string;
imageUrl?: string;
}

export type Participant = {
id: string
name: string
email: string
avatar: Avatar
type: ParticipantType
slot: Slot
activeComponents: string[]
}

export type Slot = {
index: number | null;
color: string;
textColor: string;
colorName: string;
timestamp: number;
}

export enum ParticipantType {
HOST = 'host',
GUEST = 'guest',
AUDIENCE = 'audience',
}
8 changes: 8 additions & 0 deletions packages/video/src/common/types/permissions.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Permissions = {
toggleMic?: boolean;
toggleCamera?: boolean;
toggleScreenShare?: boolean;
toggleRecording?: boolean;
toggleChat?: boolean;
toggleParticipantList?: boolean;
};
7 changes: 7 additions & 0 deletions packages/video/src/components/base/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export abstract class BaseComponent {
attach() {}
dettach() {}

protected abstract destroy(): void;
protected abstract start(): void;
}
62 changes: 62 additions & 0 deletions packages/video/src/components/video-conference/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { VideoConferenceProps } from './types';

import { VideoConference } from './index';

describe('VideoConference', () => {
it('should create VideoConference with default config when no props are provided', () => {
const videoConference = new VideoConference();
expect(videoConference).toBeDefined();
});

it('should validate and set the brand logo URL correctly', () => {
const props: VideoConferenceProps = {
brand: { logoUrl: 'https://example.com/logo.png' },
participantType: 'host',
};
const videoConference = new VideoConference(props);
expect(videoConference).toBeDefined();
});

it('should log an error for invalid brand logo URL', () => {
console.error = jest.fn();
const props: VideoConferenceProps = {
brand: { logoUrl: 'invalid-url' },
participantType: 'host',
};
expect(() => new VideoConference(props)).toThrow('[SuperViz] Invalid brand logo URL: invalid-url');
expect(console.error).toHaveBeenCalledWith('[SuperViz] Invalid brand logo URL:', 'invalid-url');
});

it('should log an error for invalid participant type', () => {
console.error = jest.fn();
const props: VideoConferenceProps = {
participantType: 'invalid-type' as any,
};
expect(() => new VideoConference(props)).toThrow('[SuperViz] Invalid participant type: invalid-type');
expect(console.error).toHaveBeenCalledWith('[SuperViz] Invalid participant type:', 'invalid-type');
});

it('should set default permissions when none are provided', () => {
const props: VideoConferenceProps = {
participantType: 'guest',
};
const videoConference = new VideoConference(props);
expect(videoConference).toBeDefined();
});

it('should set provided permissions correctly', () => {
const props: VideoConferenceProps = {
participantType: 'host',
permissions: {
toggleCamera: false,
toggleMic: false,
toggleChat: false,
toggleParticipantList: false,
toggleRecording: false,
toggleScreenShare: false,
},
};
const videoConference = new VideoConference(props);
expect(videoConference).toBeDefined();
});
});
47 changes: 47 additions & 0 deletions packages/video/src/components/video-conference/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Logger } from '../../common/utils/logger';
import { BaseComponent } from '../base';

import { VideoConferenceProps } from './types';

export class VideoConference extends BaseComponent {
private config: VideoConferenceProps;
private logger: Logger;

constructor(props?: VideoConferenceProps) {
super();
this.logger = new Logger('@superviz/video/video-conference');
this.validateProps(props);
}

private validateProps(props: VideoConferenceProps) {
if (props?.brand?.logoUrl) {
const urlPattern = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
if (!urlPattern.test(props.brand.logoUrl)) {
console.error('[SuperViz] Invalid brand logo URL:', props.brand.logoUrl);
throw new Error(`[SuperViz] Invalid brand logo URL: ${props.brand.logoUrl}`);
}
}

if (props?.participantType && !['audience', 'host', 'guest'].includes(props?.participantType)) {
console.error('[SuperViz] Invalid participant type:', props.participantType);
throw new Error(`[SuperViz] Invalid participant type: ${props.participantType}`);
}

this.config = {
styles: props?.styles || '',
brand: props?.brand || { logoUrl: undefined },
participantType: props?.participantType || 'guest',
permissions: {
toggleCamera: props?.permissions?.toggleCamera || true,
toggleMic: props?.permissions?.toggleMic || true,
toggleChat: props?.permissions?.toggleChat || true,
toggleParticipantList: props?.permissions?.toggleParticipantList || true,
toggleRecording: props?.permissions?.toggleRecording || true,
toggleScreenShare: props?.permissions?.toggleScreenShare || true,
},
};
}

protected start() {}
protected destroy() {}
}
12 changes: 12 additions & 0 deletions packages/video/src/components/video-conference/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { z } from 'zod';

import { Brand, BrandSchema } from '../../common/types/brand.types';
import { ParticipantType } from '../../common/types/participant.types';
import { Permissions } from '../../common/types/permissions.types';

export type VideoConferenceProps = {
brand?: Brand;
participantType?: ParticipantType | `${ParticipantType}`;
permissions?: Permissions;
styles?: string;
};
7 changes: 0 additions & 7 deletions packages/video/src/index.test.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/video/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {};
export { VideoConferenceProps } from './components/video-conference/types';
export { VideoConference } from './components/video-conference';

0 comments on commit a8f8cd5

Please sign in to comment.