Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add testing for ComfyUI examples #95

Merged
merged 5 commits into from
Jul 7, 2024
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
3 changes: 3 additions & 0 deletions .env_example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ DEV_SERVER_COMFYUI_URL=http://127.0.0.1:8188
# Add `--front-end-root {DEPLOY_COMFY_UI_DIR}/custom_web_versions/main/dev`
# to ComfyUI launch script to serve the custom web version.
DEPLOY_COMFYUI_DIR=/home/ComfyUI/web

# The directory containing the ComfyUI_examples repo used to extract test workflows.
EXAMPLE_REPO_PATH=tests-ui/ComfyUI_examples
7 changes: 7 additions & 0 deletions .github/workflows/test-ui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ jobs:
id: commit-message
run: echo "::set-output name=message::$(git log -1 --pretty=%B)"
working-directory: ComfyUI_frontend
- name: Checkout ComfyUI_examples
uses: actions/checkout@v4
with:
repository: "comfyanonymous/ComfyUI_examples"
path: "ComfyUI_frontend/tests-ui/ComfyUI_examples"
ref: master
- name: Skip CI
if: contains(steps.commit-message.outputs.message, '[skip ci]')
run: echo "Skipping CI as commit contains '[skip ci]'"
Expand Down Expand Up @@ -58,6 +64,7 @@ jobs:
- name: Run UI tests
run: |
npm run test:generate
npm run test:generate:examples
npm test -- --verbose
working-directory: ComfyUI_frontend
- name: Install Playwright Browsers
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ dist-ssr

# Ignore test data.
tests-ui/data/*
tests-ui/ComfyUI_examples
tests-ui/workflows/examples

# Browser tests
/test-results/
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ core extensions will be loaded.

### Test

- `git clone https://github.com/comfyanonymous/ComfyUI_examples.git` to `tests-ui/ComfyUI_examples` or the EXAMPLE_REPO_PATH location specified in .env
- `npm i` to install all dependencies
- `npm run test:generate` to fetch `tests-ui/data/object_info.json`
- `npm run test:generate:examples` to extract the example workflows
- `npm run test` to execute all unit tests.

## Deploy
Expand Down
43 changes: 22 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"typecheck": "tsc --noEmit",
"format": "prettier --write 'src/**/*.{js,ts,tsx}'",
"test": "npm run build && jest",
"test:generate:examples": "npx tsx tests-ui/extractExamples",
"test:generate": "npx tsx tests-ui/setup",
"test:browser": "npx playwright test",
"prepare": "husky || true",
Expand All @@ -24,6 +25,7 @@
"@types/node": "^20.14.8",
"babel-plugin-transform-import-meta": "^2.2.1",
"babel-plugin-transform-rename-import": "^2.3.0",
"chalk": "^5.3.0",
"fs-extra": "^11.2.0",
"husky": "^9.0.11",
"identity-obj-proxy": "^3.0.0",
Expand Down
76 changes: 76 additions & 0 deletions src/scripts/metadata/flac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
export function getFromFlacBuffer(buffer: ArrayBuffer): Record<string, string> {
const dataView = new DataView(buffer);

// Verify the FLAC signature
const signature = String.fromCharCode(...new Uint8Array(buffer, 0, 4));
if (signature !== "fLaC") {
console.error("Not a valid FLAC file");
return;
}

// Parse metadata blocks
let offset = 4;
let vorbisComment = null;
while (offset < dataView.byteLength) {
const isLastBlock = dataView.getUint8(offset) & 0x80;
const blockType = dataView.getUint8(offset) & 0x7f;
const blockSize = dataView.getUint32(offset, false) & 0xffffff;
offset += 4;

if (blockType === 4) {
// Vorbis Comment block type
vorbisComment = parseVorbisComment(
new DataView(buffer, offset, blockSize)
);
}

offset += blockSize;
if (isLastBlock) break;
}

return vorbisComment;
}

export function getFromFlacFile(file: File): Promise<Record<string, string>> {
return new Promise((r) => {
const reader = new FileReader();
reader.onload = function (event) {
const arrayBuffer = event.target.result as ArrayBuffer;
r(getFromFlacBuffer(arrayBuffer));
};
reader.readAsArrayBuffer(file);
});
}

// Function to parse the Vorbis Comment block
function parseVorbisComment(dataView: DataView): Record<string, string> {
let offset = 0;
const vendorLength = dataView.getUint32(offset, true);
offset += 4;
const vendorString = getString(dataView, offset, vendorLength);
offset += vendorLength;

const userCommentListLength = dataView.getUint32(offset, true);
offset += 4;
const comments = {};
for (let i = 0; i < userCommentListLength; i++) {
const commentLength = dataView.getUint32(offset, true);
offset += 4;
const comment = getString(dataView, offset, commentLength);
offset += commentLength;

const [key, value] = comment.split("=");

comments[key] = value;
}

return comments;
}

function getString(dataView: DataView, offset: number, length: number): string {
let string = "";
for (let i = 0; i < length; i++) {
string += String.fromCharCode(dataView.getUint8(offset + i));
}
return string;
}
53 changes: 53 additions & 0 deletions src/scripts/metadata/png.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export function getFromPngBuffer(buffer: ArrayBuffer) {
// Get the PNG data as a Uint8Array
const pngData = new Uint8Array(buffer);
const dataView = new DataView(pngData.buffer);

// Check that the PNG signature is present
if (dataView.getUint32(0) !== 0x89504e47) {
console.error("Not a valid PNG file");
return;
}

// Start searching for chunks after the PNG signature
let offset = 8;
let txt_chunks: Record<string, string> = {};
// Loop through the chunks in the PNG file
while (offset < pngData.length) {
// Get the length of the chunk
const length = dataView.getUint32(offset);
// Get the chunk type
const type = String.fromCharCode(...pngData.slice(offset + 4, offset + 8));
if (type === "tEXt" || type == "comf" || type === "iTXt") {
// Get the keyword
let keyword_end = offset + 8;
while (pngData[keyword_end] !== 0) {
keyword_end++;
}
const keyword = String.fromCharCode(
...pngData.slice(offset + 8, keyword_end)
);
// Get the text
const contentArraySegment = pngData.slice(
keyword_end + 1,
offset + 8 + length
);
const contentJson = new TextDecoder("utf-8").decode(contentArraySegment);
txt_chunks[keyword] = contentJson;
}

offset += 12 + length;
}
return txt_chunks;
}

export function getFromPngFile(file: File) {
return new Promise<Record<string, string>>((r) => {
const reader = new FileReader();
reader.onload = (event) => {
r(getFromPngBuffer(event.target.result as ArrayBuffer));
};

reader.readAsArrayBuffer(file);
});
}
Loading
Loading