Skip to content

Commit

Permalink
WIP: Add Cypress tests and data-testid attributes (#17)
Browse files Browse the repository at this point in the history
* feat(test): Add data-testid attributes for testing

* feat(test): Integrate Cypress for e2e testing

* feat(test): Add e2e test file

* Add the cypress e2e test file.

* test: data-testid's were added

* test: tests optimized

* chore: cypress test command

Use a headless Firefox browser as the default test environment.

* test: test user json for fixture added

* fix(test): Adjust test code for login window

* test: add data-testid elements to 3 components

* test: data-testid attributes added

* fix(test): splittet chat tests to e2e file

* test: added 3 ui tests

* test(fix): test script works now with electron

* test(fix): Fixed data-testid for icons

* test: added 4 tests for the config menu

* test: Add 6 new tests for the config

---------

Co-authored-by: Christian Gawron <[email protected]>
  • Loading branch information
bryanlewicki and cgawron authored Apr 24, 2024
1 parent 5780a86 commit 666b105
Show file tree
Hide file tree
Showing 23 changed files with 2,092 additions and 106 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
coverage/
dist/*
node_modules/
cypress/screenshots
*.log

# OS generated files
Expand Down
9 changes: 9 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from "cypress";

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
138 changes: 138 additions & 0 deletions cypress/e2e/e2eTest.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
describe("Chat", () => {
beforeEach(() => {
cy.intercept('GET', 'https://openai.ki.fh-swf.de/api/user', { fixture: 'testUser.json' }).as('getUser');
cy.visit("http://localhost:5173/");
cy.wait('@getUser');
cy.wait(2000)

cy.intercept('POST', 'https://openai.ki.fh-swf.de/api/v1/chat/completions', (req) => {
const fakeResponseData = [
{
"id": "chatcmpl-9FNy2VTHzcWXJUkKXOholEKFNV5MO",
"object": "chat.completion.chunk",
"created": 1713454078,
"model": "gpt-4-0125-preview",
"system_fingerprint": "fp_1d2ae78ab7",
"choices": [
{ "index": 0, "delta": { "role":"assistant", "content": "" }, "logprobs": null, "finish_reason": null }
]
},
{
"id": "chatcmpl-9FNy2VTHzcWXJUkKXOholEKFNV5MO",
"object": "chat.completion.chunk",
"created": 1713454078,
"model": "gpt-4-0125-preview",
"system_fingerprint": "fp_1d2ae78ab7",
"choices": [
{ "index": 0, "delta": { "content": "It" }, "logprobs": null, "finish_reason": null }
]
},
{
"id": "chatcmpl-9FNy2VTHzcWXJUkKXOholEKFNV5MO",
"object": "chat.completion.chunk",
"created": 1713454078,
"model": "gpt-4-0125-preview",
"system_fingerprint": "fp_1d2ae78ab7",
"choices": [
{ "index": 0, "delta": { "content": "looks" }, "logprobs": null, "finish_reason": "stop" }
]
},
];

fakeResponseData.push("data: [DONE]");

req.reply({
statusCode: 200,
body: fakeResponseData
});
}).as("messageResponse");

cy.getDataTestId("ChatTextArea").click().type("Cypress wrote this!").should("have.text", "Cypress wrote this!");
});

it("Sending a message with the send button", () => {
cy.getDataTestId("SendMessageBtn").click();
cy.wait("@messageResponse");
cy.getDataTestId("ChatTextArea").should("have.text", "");
cy.getDataTestId("ChatListContainer").should("be.visible");
cy.getDataTestId("ChatMessage").each((message) => {
cy.wrap(message).should("contain.text", "Cypress wrote this!");
});
});

it("Sending 2 messages and checking if both are in the chat", () => {
cy.getDataTestId("SendMessageBtn").click();
//cy.getDataTestId("ChatTextArea").should("have.text", "");
cy.wait(2000);
cy.getDataTestId("ChatListContainer").should("be.visible");
cy.getDataTestId("ChatMessage").each((message) => {
cy.wrap(message).should("contain.text", "Cypress wrote this!");
});
cy.getDataTestId("ChatTextArea").click().type("Cypress also wrote this!");
cy.getDataTestId("ChatTextArea").should(
"have.text",
"Cypress also wrote this!"
);
cy.getDataTestId("SendMessageBtn").click();
cy.getDataTestId("ChatTextArea").should("have.text", "");
cy.getDataTestId("ChatListContainer").should("be.visible");

cy.getDataTestId("ChatListContainer").within(() => {
// Überprüfe die erste Nachricht
cy.getDataTestId("ChatMessage")
.eq(0)
.should("contain", "Cypress wrote this!");

// Überprüfe die zweite Nachricht
cy.getDataTestId("ChatMessage")
.eq(1)
.should("contain", "Cypress also wrote this!");
});
});

it("Sending a message with enter", () => {
cy.getDataTestId("ChatTextArea").click().type("{enter}");
//cy.getDataTestId("ChatTextArea").should("have.text", "");
cy.wait(2000);
cy.getDataTestId("ChatListContainer").should("be.visible");
cy.getDataTestId("ChatMessage").each((message) => {
cy.wrap(message).should("contain.text", "Cypress wrote this!");
});
});

it("Changing the message sending to ctrl+enter and sending it", () => {
// Change message sending method to use ctrl+enter
cy.getDataTestId("BottomLeftSideBar").find("i").eq(3).click();
cy.getDataTestId("SendMessageSelect").select("COMMAND_ENTER");
cy.getDataTestId("SettingsCloseBtn").click();

// Try sending message using Enter
cy.getDataTestId("ChatTextArea").click().type("{enter}").should("have.text", "Cypress wrote this!");

// Send message using ctrl+Enter
cy.getDataTestId("ChatTextArea").click().type("{ctrl}{enter}").should("have.text", "");

// Check if the message has been sent
cy.getDataTestId("ChatMessage").each((message) => {
cy.wrap(message).should("contain.text", "Cypress wrote this!");
});
});

it("Sending a message and clearing the chatlog", () => {
// Send message
cy.getDataTestId("SendMessageBtn").click();
cy.getDataTestId("ChatListContainer").find('[data-testid="ChatMessage"]').should('exist');

// Clear chatlog
cy.getDataTestId("ClearMessageBtn").click();
cy.getDataTestId("ChatListContainer").should('not.exist');

// Check if message can be sent again
const message = "Cypress wrote this!";
cy.getDataTestId("ChatTextArea").type(message).should("have.value", message);
cy.getDataTestId("SendMessageBtn").click();
cy.getDataTestId("ChatListContainer").should('exist');
});

});

196 changes: 196 additions & 0 deletions cypress/e2e/uiTest.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
describe("User Interface", () => {
beforeEach(() => {

cy.intercept('GET', 'https://openai.ki.fh-swf.de/api/user', { fixture: 'testUser.json' }).as('getUser');
cy.visit("http://localhost:5173/");
cy.wait('@getUser');
// Check if the page has loaded successfully (Status code 200)
cy.request("http://localhost:5173/").should((response) => {
expect(response.status).to.eq(200);
});
});

it("Check the headline", () => {
cy.getDataTestId("HeaderTitle").contains(
"K!mpuls, der datenschutzfreundliche Chatbot der FH Südwestfalen"
);
});
/*
it.only('Check if headline is equal to the conversation', () => {
cy.getDataTestId("BottomLeftSideBar").find("i").eq(1).click();
cy.getDataTestId("ConversationList").within(() => {
cy.get('[data-testid="Conversation"]').eq(0).find('[data-testid="ConversationTitle"]').invoke("text").as("conversationText").then(() => {
//cy.get('[data-testid="HeaderTitle"]').should("contain.text", conversationText);
cy.getDataTestId("HeaderTitle").get("text").as("headerText");
cy.log(this.headerText);
});
});
});
*/
it("Hide and show the conversation sidebar", () => {
cy.getDataTestId("ConversationSideBar").should("exist");
cy.getDataTestId("ConversationSideBarBtn").click();
cy.getDataTestId("ConversationSideBar").should("not.exist");
cy.getDataTestId("ConversationSideBarBtn").click();
cy.getDataTestId("ConversationSideBar").should("exist");
});

it("Switching between Apps and History", () => {
cy.getDataTestId("AppsList").should("exist", "be.visible");
cy.getDataTestId("ConversationList").should("not.exist");
cy.getDataTestId("BottomLeftSideBar").find("i").eq(1).click();
cy.getDataTestId("AppsList").should("not.exist");
cy.getDataTestId("ConversationList").should("exist", "be.visible");
cy.getDataTestId("BottomLeftSideBar").find("i").eq(0).click();
cy.getDataTestId("ConversationList").should("not.exist");
cy.getDataTestId("AppsList").should("exist", "be.visible");
});

it("Conversation search bar input works", () => {
cy.getDataTestId("ConversationSearchBar").find('input').should('exist').then(($input) => {
cy.wrap($input).type("search input works").should("have.value", "search input works");
});
});

it("Create and edit new conversation", () => {
cy.getDataTestId("BottomLeftSideBar").find("i").eq(1).click();
cy.getDataTestId("ConversationCreateBtn").click();
cy.getDataTestId("HeaderTitle").contains("Dies ist ein neues Gespräch");
cy.getDataTestId("ConversationList").within(() => {
cy.get('[data-testid="Conversation"]').eq(0).find('[data-testid="ConversationTitle"]').contains("Dies ist ein neues Gespräch");
cy.getDataTestId("editConversation").find("i").eq(0).click({ force: true });
cy.getDataTestId("editConversationTextArea").find("textarea").clear().type("edit conversation text");
cy.getDataTestId("editConversationSaveBtn").click();
cy.get('[data-testid="Conversation"]').eq(0).find('[data-testid="ConversationTitle"]').contains("edit conversation text");
});
cy.getDataTestId("HeaderTitle").contains("edit conversation text");
});

it("Show infos", () => {
cy.getDataTestId("InformationWindow").should("not.exist");
cy.getDataTestId("LeftSideBar").find("i").eq(0).click(); //Clicks the Info with the ?
cy.getDataTestId("InformationWindow").should("be.visible");
cy.getDataTestId("InformationWindow").should("exist");
});
});

describe("Dark Mode", () => {
beforeEach(() => {
cy.intercept('GET', 'https://openai.ki.fh-swf.de/api/user', { fixture: 'testUser.json' }).as('getUser');
cy.visit("http://localhost:5173/");
cy.wait('@getUser');
});

it("Down Left Button", () => {
cy.get("html").should("have.attr", "data-theme", "light");
cy.getDataTestId("BottomLeftSideBar").find("i").eq(2).click();
cy.get("html").should("have.attr", "data-theme", "dark");
cy.getDataTestId("BottomLeftSideBar").find("i").eq(2).click();
cy.get("html").should("have.attr", "data-theme", "light");
});

it("Top Right Button", () => {
cy.get("html").should("have.attr", "data-theme", "light");
cy.getDataTestId("TopRightDarkModeBtn").click();
cy.get("html").should("have.attr", "data-theme", "dark");
cy.getDataTestId("TopRightDarkModeBtn").click();
cy.get("html").should("have.attr", "data-theme", "light");
});

it("In Settings", () => {
cy.getDataTestId("BottomLeftSideBar").find("i").eq(3).click();
cy.get("html").should("have.attr", "data-theme", "light");
cy.getDataTestId("OptionDarkModeSelect").select("dark");
cy.get("html").should("have.attr", "data-theme", "dark");
cy.getDataTestId("OptionDarkModeSelect").select("light");
cy.get("html").should("have.attr", "data-theme", "light");
});
});

describe("User Information", () => {
beforeEach(() => {
cy.intercept('GET', 'https://openai.ki.fh-swf.de/api/user', { fixture: 'testUser.json' }).as('getUser');
cy.visit("http://localhost:5173/");
cy.wait('@getUser');
});

it("Open and close user information", () => {
cy.getDataTestId("UserInformation").should("not.exist");
cy.getDataTestId("UserInformationBtn").click();
cy.getDataTestId("UserInformation").should("be.visible", "exist");
cy.getDataTestId("UserInformationCloseBtn").click();
cy.getDataTestId("UserInformation").should("not.exist");
});
});

describe("Config Menu", () => {
beforeEach(() => {
cy.intercept('GET', 'https://openai.ki.fh-swf.de/api/user', { fixture: 'testUser.json' }).as('getUser');
cy.visit("http://localhost:5173/");
cy.wait('@getUser');
cy.getDataTestId("BottomLeftSideBar").find("i").eq(3).click();
});

it("Dark Mode", () => {
cy.get("html").should("have.attr", "data-theme", "light");
cy.getDataTestId("OptionDarkModeSelect").select("dark");
cy.get("html").should("have.attr", "data-theme", "dark");
cy.getDataTestId("OptionDarkModeSelect").select("light");
cy.get("html").should("have.attr", "data-theme", "light");
});

it("Change Send Message Button", () => {
cy.getDataTestId("SendMessageSelect").select("COMMAND_ENTER").should("have.value", "COMMAND_ENTER");
cy.getDataTestId("SendMessageSelect").select("ALT_ENTER").should("have.value", "ALT_ENTER");
cy.getDataTestId("SendMessageSelect").select("ENTER").should("have.value", "ENTER");
});

it("Change Language", () => {
cy.getDataTestId("SetLanguageSelect").select("English").should("have.value", "en");
cy.getDataTestId("SetLanguageSelect").select("Deutsch").should("have.value", "de");
cy.getDataTestId("SetLanguageSelect").select("简体中文").should("have.value", "zh");
cy.getDataTestId("SetLanguageSelect").select("日本").should("have.value", "jp");
});

it("Change Fontsize", () => {
cy.getDataTestId('SettingsHeader').find('h5').should('have.css', 'font-size', '12px');
cy.getDataTestId("ChangeFontSizeSelect").select("Small").should("have.value", "small");
cy.getDataTestId('SettingsHeader').find('h5').should('have.css', 'font-size', '12px');
cy.getDataTestId("ChangeFontSizeSelect").select("Default").should("have.value", "default");
cy.getDataTestId('SettingsHeader').find('h5').should('have.css', 'font-size', '14px');
cy.getDataTestId("ChangeFontSizeSelect").select("Middle").should("have.value", "middle");
cy.getDataTestId('SettingsHeader').find('h5').should('have.css', 'font-size', '13px');
cy.getDataTestId("ChangeFontSizeSelect").select("Large").should("have.value", "large");
cy.getDataTestId('SettingsHeader').find('h5').should('have.css', 'font-size', '16px');
});

it("Change OpenAI Model", () => {
cy.getDataTestId('ChangeAIModelSelect').select("gpt-4-turbo-preview").should("have.value", "gpt-4-turbo-preview");
cy.getDataTestId('ChangeAIModelSelect').select("gpt-4").should("have.value", "gpt-4");
cy.getDataTestId('ChangeAIModelSelect').select("gpt-3.5-turbo").should("have.value", "gpt-3.5-turbo");
});

it("Set max tokens input", () => {
cy.getDataTestId('MaxTokensInput').clear().should("have.value", "0").type("{selectall}1024").should("have.value", "1024");
});

it("Set temperature input", () => {
cy.getDataTestId('SetTemperatureInput').clear().should("have.value", "0").type("{selectall}1024").should("have.value", "1024");
});

it("Set top P input", () => {
cy.getDataTestId('SetTopPInput').clear().should("have.value", "0").type("{selectall}1024").should("have.value", "1024");
});

it("Set api base url input", () => {
cy.getDataTestId('ApiBaseURLInput').clear().should("have.value", "").type("a_cypress_input_test").should("have.value", "a_cypress_input_test");
});

it("Set api key input", () => {
cy.getDataTestId('APIKeyInput').clear().should("have.value", "").type("a_cypress_input_test").should("have.value", "a_cypress_input_test");
});

it.only("Set organisation id input", () => {
cy.getDataTestId('APIOrganisationIDInput').clear().should("have.value", "").type("a_cypress_id_test").should("have.value", "a_cypress_id_test");
});
});
5 changes: 5 additions & 0 deletions cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "[email protected]",
"body": "Fixtures are a great way to mock data for responses to routes"
}
6 changes: 6 additions & 0 deletions cypress/fixtures/testUser.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "None None",
"email": "christian.gawron%[email protected]",
"sub": "b49b699d-d279-4860-8387-70d8785ad885",
"preferred_username": "test_gpt"
}
Loading

0 comments on commit 666b105

Please sign in to comment.