Skip to content
Open
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 .husky/post-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { printf >&2 "\n%s\n\n" "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-checkout' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks')."; exit 2; }
git lfs post-checkout "$@"
3 changes: 3 additions & 0 deletions .husky/post-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { printf >&2 "\n%s\n\n" "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-commit' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks')."; exit 2; }
git lfs post-commit "$@"
3 changes: 3 additions & 0 deletions .husky/post-merge
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { printf >&2 "\n%s\n\n" "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-merge' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks')."; exit 2; }
git lfs post-merge "$@"
3 changes: 3 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { printf >&2 "\n%s\n\n" "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'pre-push' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks')."; exit 2; }
git lfs pre-push "$@"
20 changes: 20 additions & 0 deletions README_PR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## ✅ PR: Add Cypress test with mock Stakwork endpoints for Hivechat Chat Mode

**Summary:**
- Adds fixture file with mock Stakwork responses
- Adds Cypress command to intercept and mock `/hivechat/response` and webhook endpoints
- New e2e test covering text, code & screen artifacts, and action dialogs
- Configurable mock/real endpoints via `useMocks`

**Why:** Enable consistent backend-independent tests.
Resolves part of https://github.com/stakwork/sphinx-tribes-frontend/pull/1395

**How to run:**
```bash
yarn cy:open # UI mode
yarn cy:run # headless
```

Toggle mock/real: edit `cypress.config.js` → `env.useMocks`

Ready for review 🚀
10 changes: 10 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { defineConfig } = require("cypress");

module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3007',
env: {
useMocks: true
}
}
});
42 changes: 42 additions & 0 deletions cypress/e2e/hivechat_flow.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
describe('Hivechat Flow with Mock Stakwork API', () => {
beforeEach(() => {
cy.mockStakworkAPI();
cy.login('testuser'); // use your login helper
cy.visit('/workspace/123/hivechat/456');
cy.wait(1000);
});

it('Completes hivechat flow', () => {
cy.get('[data-testid="chat-mode-button"]').click();
cy.get('[data-testid="message-input"]').type('Lets create a new @ticket');
cy.get('[data-testid="send-message-button"]').click();

cy.wait('@hivechatResponse');
cy.get('[data-testid="artifact-tab-Text"]').should('be.visible');
cy.get('[data-testid="artifact-content-text"]').should('contain', 'Market Research');

cy.get('[data-testid="message-input"]').clear().type('Yes sounds good');
cy.get('[data-testid="send-message-button"]').click();

cy.wait('@hivechatResponse');
cy.get('[data-testid="artifact-tab-Code"]').should('be.visible').click();
cy.get('[data-testid="artifact-content-code"]').should('contain', 'LeaderboardPage');

cy.get('[data-testid="artifact-tab-Screen"]').click();
cy.get('[data-testid="artifact-content-screen"]').should('be.visible');

cy.get('[data-testid="action-dialog"]').contains('Yes').click();

cy.wait('@hivechatResponse');
cy.get('[data-testid="artifact-content-code"]').should('contain', 'applyPatch');

cy.get('[data-testid="action-dialog"]').contains('Yes').click();

cy.wait('@hivechatResponse');
cy.get('[data-testid="message-history"]').should('contain', 'Patch applied successfully');
});

afterEach(() => {
cy.logout();
});
});
133 changes: 133 additions & 0 deletions cypress/fixtures/stakwork-responses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
export const stakworkResponses = {
initialResponse: {
value: {
chatId: "cvljgu7paij1jhtehg9g",
messageId: "cvljh5npaij1jhtehga0",
response: "Ok here's the plan for you to review...",
sourceWebsocketId: "52a3e86e-d466-40a4-a4a8-e88938653335",
artifacts: [
{
id: "111-222-333-444",
type: "action",
content: {
actionText: "",
options: [
{
action_type: "chat",
option_label: "Give me feedback",
option_response: "textbox",
webhook: "https://jobs.stakwork.com/customer_webhooks/v1?..."
}
]
}
},
{
id: "550e8400-e29b-41d4-a716-446655440123",
messageId: "msg_123456",
type: "text",
content: {
text_type: "markdown",
content: "Creating a plan for market domination..."
}
}
]
}
},
codeScreenResponse: {
value: {
chatId: "cvljgu7paij1jhtehg9g",
messageId: "cvljh5npaij1jhtehga0",
response: "Alright I've implemented the code below...",
sourceWebsocketId: "52a3e86e-d466-40a4-a4a8-e88938653335",
artifacts: [
{
id: "111-222-333-444",
type: "action",
content: {
actionText: "I detected an error do you want to see the logs?",
options: [
{
action_type: "chat",
option_label: "Give me feedback",
option_response: "textbox",
webhook: "https://jobs.stakwork.com/customer_webhooks/v1?..."
},
{
action_type: "button",
option_label: "Yes",
option_response: "Yes",
webhook: "https://jobs.stakwork.com/customer_webhooks/v1?..."
}
]
}
},
{
id: "550e8400-e29b-41d4-a716-446655440001",
messageId: "msg_123456",
type: "visual",
content: {
visual_type: "screen",
url: "https://community.sphinx.chat/leaderboard"
}
},
{
id: "550e8400-e29b-41d4-a716-446655440123",
messageId: "msg_123456",
type: "text",
content: {
text_type: "code",
content: "import React, { useState } from 'react';..."
}
}
]
}
},
logsResponse: {
value: {
chatId: "cvljgu7paij1jhtehg9g",
messageId: "cvljh5npaij1jhtehga0",
response: "OK here's the logs, they should be streaming through now...",
sourceWebsocketId: "52a3e86e-d466-40a4-a4a8-e88938653335",
artifacts: [
{
id: "111-222-333-444",
type: "action",
content: {
actionText: "how about we fix this with patch 1523.patch",
options: [
{
action_type: "chat",
option_label: "Give me feedback",
option_response: "textbox",
webhook: "https://jobs.stakwork.com/customer_webhooks/v1?..."
},
{
action_type: "button",
option_label: "Yes",
option_response: "Yes",
webhook: "https://jobs.stakwork.com/customer_webhooks/v1?..."
}
]
}
},
{
id: "550e8400-e29b-41d4-a716-446655440123",
messageId: "msg_123456",
type: "text",
content: {
text_type: "code",
language: "typescript",
content: "function applyPatch(...) { ... }"
}
}
]
}
},
finalResponse: {
value: {
chatId: "cvljgu7paij1jhtehg9g",
messageId: "cvljh5npaij1jhtehga0",
response: "Patch applied successfully! The fix has been deployed."
}
}
};
21 changes: 21 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { stakworkResponses } from '../fixtures/stakwork-responses';

Cypress.Commands.add('mockStakworkAPI', () => {
if (Cypress.env('useMocks') === false) return;

let responseCounter = 0;

cy.intercept('POST', '**/hivechat/response', (req) => {
let res = stakworkResponses.finalResponse;
if (responseCounter === 0) res = stakworkResponses.initialResponse;
else if (responseCounter === 1) res = stakworkResponses.codeScreenResponse;
else if (responseCounter === 2) res = stakworkResponses.logsResponse;
responseCounter++;
req.reply({ statusCode: 200, body: res });
}).as('hivechatResponse');

cy.intercept('POST', '**/customer_webhooks/**', {
statusCode: 200,
body: { success: true }
}).as('webhookAction');
});