Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 65 additions & 85 deletions __test__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// import k21 from '@k21'
import { K21Pipeline } from '@k21'
import { K21 } from '@k21'
import fs from 'fs';
import path from 'path';
import os from 'os';

jest.setTimeout(20000); // Set global timeout

describe('K21Pipeline', () => {
let pipeline: K21Pipeline
describe('K21', () => {
let k21: K21
let tempDir: string;

beforeEach(() => {
pipeline = new K21Pipeline()
k21 = new K21()
// Create unique temp directory for each test
tempDir = path.join(os.tmpdir(), `k21-test-${Date.now()}`);
fs.mkdirSync(tempDir, { recursive: true });
Expand All @@ -26,23 +26,21 @@ describe('K21Pipeline', () => {

describe('initialization', () => {
test('should initialize with null values', () => {
expect(pipeline['capturer']).toBeNull()
expect(pipeline['uploader']).toBeNull()
expect(pipeline['processor']).toBeNull()
expect(k21['capturer']).toBeNull()
expect(k21['uploader']).toBeNull()
expect(k21['processor']).toBeNull()
})
})

describe('setCapturer', () => {
test('should set basic config correctly', () => {
const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: false
duration: 5,
}
pipeline.setCapturer(config)
expect(pipeline['capturer']).toEqual({
...pipeline['defaultConfig'],
k21.setCapturer(config)
expect(k21['capturer']).toEqual({
...k21['defaultConfig'],
...config
})
})
Expand All @@ -53,16 +51,14 @@ describe('K21Pipeline', () => {

const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: true,
outputDirVideo: videoDir,
videoChunkDurationInSeconds: 10,
saveScreenshot: false
duration: 5,
saveVideoTo: videoDir,
videoChunkDuration: 10,
}
pipeline.setCapturer(config)
expect(pipeline['capturer']).toEqual({
...pipeline['defaultConfig'],
...pipeline['defaultConfigSaveVideo'],
k21.setCapturer(config)
expect(k21['capturer']).toEqual({
...k21['defaultConfig'],
...k21['defaultConfigSaveVideo'],
...config
})
})
Expand All @@ -73,15 +69,13 @@ describe('K21Pipeline', () => {

const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: true,
outputDirScreenshot: screenshotDir
duration: 5,
saveScreenshotTo: screenshotDir
}
pipeline.setCapturer(config)
expect(pipeline['capturer']).toEqual({
...pipeline['defaultConfig'],
...pipeline['defaultConfigSaveScreenshot'],
k21.setCapturer(config)
expect(k21['capturer']).toEqual({
...k21['defaultConfig'],
...k21['defaultConfigSaveScreenshot'],
...config
})
})
Expand All @@ -94,86 +88,76 @@ describe('K21Pipeline', () => {

const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: true,
outputDirVideo: videoDir,
videoChunkDurationInSeconds: 10,
saveScreenshot: true,
outputDirScreenshot: screenshotDir
duration: 5,
saveScreenshotTo: screenshotDir,
saveVideoTo: videoDir,
videoChunkDuration: 10,
}
pipeline.setCapturer(config)
expect(pipeline['capturer']).toEqual({
...pipeline['defaultConfig'],
...pipeline['defaultConfigSaveVideo'],
...pipeline['defaultConfigSaveScreenshot'],
k21.setCapturer(config)
expect(k21['capturer']).toEqual({
...k21['defaultConfig'],
...k21['defaultConfigSaveVideo'],
...k21['defaultConfigSaveScreenshot'],
...config
})
})

test('should throw error when setting capturer with uploader present', () => {
pipeline.setUploader('test-uploader')
expect(() => pipeline.setCapturer({
k21.setUploader('test-uploader')
expect(() => k21.setCapturer({
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: false
})).toThrow('Cannot set Capturer when Uploader is already set')
duration: 5
})).toThrow('Cannot set Capturer when Uploader is already set')
})
})

describe('setUploader', () => {
test('should throw error when setting uploader with capturer present', () => {
pipeline.setCapturer({
k21.setCapturer({
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: false
duration: 5
})
expect(() => pipeline.setUploader('test-uploader')).toThrow(
expect(() => k21.setUploader('test-uploader')).toThrow(
'Cannot set Uploader when Capturer is already set'
)
})
})

describe('run', () => {
test('should throw error when neither capturer nor uploader is set', async () => {
expect(pipeline.run()).rejects.toThrow(
expect(k21.run()).rejects.toThrow(
'Either Capturer or Uploader must be set'
)
})

test('should run with basic capture config', async () => {
const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: false
duration: 5
}
pipeline.setCapturer(config)
expect(pipeline.run()).resolves.not.toThrow()
k21.setCapturer(config)
expect(k21.run()).resolves.not.toThrow()
})

test('should run with video capture config', async () => {
const videoDir = path.join(tempDir, 'videos');
fs.mkdirSync(videoDir, { recursive: true });

const recordLengthInSeconds = 5
const videoChunkDurationInSeconds = 10
const duration = 5
const videoChunkDuration = 10

const fullChunks = Math.floor(recordLengthInSeconds / videoChunkDurationInSeconds)
const extraChunk = recordLengthInSeconds % videoChunkDurationInSeconds > 0 ? 1 : 0
const fullChunks = Math.floor(duration / videoChunkDuration)
const extraChunk = duration % videoChunkDuration > 0 ? 1 : 0
const expectedNumberOfMp4Files = fullChunks + extraChunk

const config = {
fps: 1,
recordLengthInSeconds,
saveVideo: true,
outputDirVideo: videoDir,
videoChunkDurationInSeconds,
saveScreenshot: false
duration: duration,
saveVideoTo: videoDir,
videoChunkDuration: videoChunkDuration,
}
pipeline.setCapturer(config)
await expect(pipeline.run()).resolves.not.toThrow()
k21.setCapturer(config)
await expect(k21.run()).resolves.not.toThrow()


// Check for video file
Expand All @@ -197,13 +181,11 @@ describe('K21Pipeline', () => {

const config = {
fps,
recordLengthInSeconds,
saveVideo: false,
saveScreenshot: true,
outputDirScreenshot: screenshotDir
}
pipeline.setCapturer(config)
await expect(pipeline.run()).resolves.not.toThrow();
duration: recordLengthInSeconds,
saveScreenshotTo: screenshotDir
}
k21.setCapturer(config)
await expect(k21.run()).resolves.not.toThrow();

// Check number of screenshots
const files = fs.readdirSync(screenshotDir);
Expand All @@ -214,24 +196,22 @@ describe('K21Pipeline', () => {
test('should return empty array for basic capture without processor', async () => {
const config = {
fps: 1,
recordLengthInSeconds: 5,
saveVideo: false,
saveScreenshot: false
duration: 5
}
pipeline.setCapturer(config)
const result = await pipeline.run()
k21.setCapturer(config)
const result = await k21.run()
expect(result).toEqual([])
})

test('should return processed images when processor is set', async () => {
const config = {
fps: 1,
recordLengthInSeconds: 2,
duration: 2,
}
pipeline.setCapturer(config)
pipeline.setProcessor({}) // Add mock processor
k21.setCapturer(config)
k21.setProcessor({}) // Add mock processor

const result = await pipeline.run()
const result = await k21.run()
expect(Array.isArray(result)).toBe(true)
expect(result.length).toBeGreaterThan(0)

Expand Down
4 changes: 2 additions & 2 deletions bin/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { K21Pipeline } from './k21';
export { K21Pipeline };
import { K21 } from './k21';
export { K21 };
4 changes: 2 additions & 2 deletions bin/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.K21Pipeline = void 0;
exports.K21 = void 0;
// import * as lib from './lib'
const k21_1 = require("./k21");
Object.defineProperty(exports, "K21Pipeline", { enumerable: true, get: function () { return k21_1.K21Pipeline; } });
Object.defineProperty(exports, "K21", { enumerable: true, get: function () { return k21_1.K21; } });
38 changes: 16 additions & 22 deletions bin/k21.d.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
/**
* Configuration options for screen capture
* Controls capture parameters, file saving behavior,
* and output locations for video and screenshots
* Controls capture parameters and output locations for video and screenshots
* @example
* // Basic capture without saving
* // Basic capture configuration
* const config: CaptureConfig = {
* fps: 1,
* recordLengthInSeconds: 60
* duration: 60
* }
*
* // Capture with video saving
* // Capture with saving options
* const config: CaptureConfig = {
* fps: 1,
* recordLengthInSeconds: 60,
* saveVideo: true,
* outputDirVideo: '/path/to/videos',
* videoChunkDurationInSeconds: 60
* duration: 60,
* saveVideoTo: '/path/to/videos',
* videoChunkDuration: 60
* }
*/
interface CaptureConfig {
/** Frames per second for capture. Default: 1 */
fps?: number;
/** Total duration of capture in seconds. Default: 10 */
recordLengthInSeconds?: number;
/** Whether to save screenshots during capture. Default: false */
saveScreenshot?: boolean;
/** Directory path for saving screenshots. Required if saveScreenshot is true */
outputDirScreenshot?: string;
/** Whether to save video during capture. Default: false */
saveVideo?: boolean;
/** Directory path for saving video files. Required if saveVideo is true */
outputDirVideo?: string;
/** Duration of each video chunk in seconds. Required if saveVideo is true. Default: 60 */
videoChunkDurationInSeconds?: number;
duration?: number;
/** Path where screenshots should be saved. If not provided, screenshots won't be saved */
saveScreenshotTo?: string;
/** Path where video should be saved. If not provided, video won't be saved */
saveVideoTo?: string;
/** Duration of each video chunk in seconds. Default: 60 */
videoChunkDuration?: number;
}
/** Configuration for vision-based processing using external vision APIs */
interface VisionConfig {
Expand Down Expand Up @@ -82,7 +76,7 @@ interface ImageData {
/** Type of processing applied to the frame (e.g., "OCR", "CLASSIFICATION") */
processingType: string;
}
declare class K21Pipeline {
declare class K21 {
private capturer;
private uploader;
private processor;
Expand Down Expand Up @@ -132,4 +126,4 @@ declare class K21Pipeline {
*/
run(): Promise<ImageData[]>;
}
export { K21Pipeline, ImageData, CaptureConfig };
export { K21, ImageData, CaptureConfig };
13 changes: 4 additions & 9 deletions bin/k21.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.K21Pipeline = void 0;
exports.K21 = void 0;
const k21_internal_1 = __importDefault(require("./k21_internal"));
class K21Pipeline {
class K21 {
capturer;
uploader;
processor;
defaultCaptureConfig = {
fps: 1,
recordLengthInSeconds: 10,
saveVideo: false,
outputDirVideo: '',
videoChunkDurationInSeconds: 60,
saveScreenshot: false,
outputDirScreenshot: '',
duration: 10,
};
defaultProcessorConfig = {
processingType: 'OCR',
Expand Down Expand Up @@ -127,4 +122,4 @@ class K21Pipeline {
}
}
}
exports.K21Pipeline = K21Pipeline;
exports.K21 = K21;
4 changes: 2 additions & 2 deletions k21/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// import * as lib from './lib'
import { K21Pipeline } from './k21'
export { K21Pipeline }
import { K21 } from './k21'
export { K21 }
Loading
Loading