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

Setup E2E testing Infrastructure #188

Open
wants to merge 13 commits into
base: next
Choose a base branch
from
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,12 @@ export MOCK_GS1_SERVICE_API_KEY=test456 # Mock GS1 service API key
# Run seeding scripts
./seeding/idr-data.sh
./seeding/mock-gs1-data.sh
```

## End-to-end testing
```bash
# Run end-to-end testing scripts
docker-compose up -d
ThanhDoDuy marked this conversation as resolved.
Show resolved Hide resolved
yarn start:e2e-test
yarn cypress run
```
ThanhDoDuy marked this conversation as resolved.
Show resolved Hide resolved
7,079 changes: 7,079 additions & 0 deletions app-config.e2e.json

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from 'cypress';

export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3003', // Replace with your application's base URL
supportFile: false, // Disable the default support file if not needed
specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', // Specifies the test file pattern
video: false, // Disable video recording (optional)
chromeWebSecurity: false, // Helps bypass security restrictions (if needed)
retries: {
runMode: 2, // Retries in headless mode
openMode: 0, // No retries in interactive mode
},
defaultCommandTimeout: 4000,
defaultBrowser: "chrome"
},
});
106 changes: 106 additions & 0 deletions cypress/e2e/Function_test/issueDPP.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

describe('Facility Links Test', () => {
ThanhDoDuy marked this conversation as resolved.
Show resolved Hide resolved
beforeEach(() => {
// Load app config JSON
cy.fixture('app-config.json').then((data) => {
Cypress.env('AppConfig', data);
});
});

it('should access the right the app config data', () => {
const AppConfig = Cypress.env('AppConfig');
expect(AppConfig?.name).to.eq('CHERRIES SUPPLY CHAIN TRACEABILITY');
});

it('should visit the homepage, navigate to "Orchard Facility", handle API calls, and show success message', () => {
const AppConfig = Cypress.env('AppConfig');
// Visit the homepage
cy.visit('/');

// Verify the "Orchard Facility" link exists and contains the correct text
cy.contains('a', 'Orchard Facility') // Find <a> tag by text
.should('be.visible') // Ensure it's visible
.and('not.be.disabled') // Ensure it's clickable
.click(); // Click the link

// Verify navigation to the correct page
cy.url().should('include', '/orchard-facility');
// Intercept API call triggered by clicking "ISSUE DPP"
const shemaDPP = AppConfig.apps[0]?.features[0]?.components[0].props?.schema?.url;
const appService = AppConfig.apps[0]?.features[0]?.services[0]?.parameters[0];
cy.intercept('GET', shemaDPP)
.as('getProductSchema'); // Create an alias for this request

// Check if "ISSUE DPP" button appears and is interactable
cy.contains('a', 'Issue DPP') // Find button by text
.should('be.visible')
.and('not.be.disabled')
.click();

// Wait for the API call
cy.wait('@getProductSchema', { timeout: 20000 }).then((interception) => {
expect(interception?.response?.statusCode).to.eq(200);
});

const API_ENDPOINT = {
ISSUE_BITSTRING_STATUS_LIST: "/agent/issueBitstringStatusList",
VCKit_URL: appService?.vckit?.vckitAPIUrl + '/credentials/issue',
STORAGE_URL: appService?.storage?.url,
IDR_URL: appService?.dlr?.dlrAPIUrl + appService?.dlr?.linkRegisterPath,
};
cy.intercept('POST', API_ENDPOINT.ISSUE_BITSTRING_STATUS_LIST).as('issueBitStringStatusList');
cy.intercept('POST', API_ENDPOINT.VCKit_URL).as('issueCredentials');
cy.intercept('POST', API_ENDPOINT.STORAGE_URL).as('storeVC');
cy.intercept('POST', API_ENDPOINT.IDR_URL).as('linkResolverRegister');

// Check if "Submit" button appears after API response
cy.contains('button', 'Submit')
.should('be.visible')
.and('not.be.disabled')
.click();

// await API create credential status
cy.wait('@issueBitStringStatusList').then((interception) => {
expect(interception?.response?.statusCode).to.eq(200);
cy.log('Completed: issueBitstringStatusList');
});

// await API issue VC
cy.wait('@issueCredentials').then((interception) => {
expect(interception?.response?.statusCode).to.eq(201);
cy.log('Completed: issueCredentials');
});

// await API storage VC
cy.wait('@storeVC').then((interception) => {
expect(interception?.response?.statusCode).to.eq(201);
cy.log('Completed: storeVC');

// Extract the URI from the response
const { uri, hash, key } = interception?.response?.body;
expect(uri).to.not.be.undefined;
expect(hash).to.not.be.undefined;
expect(key).to.not.be.undefined;
cy.request('GET', uri).then((response) => {
expect(response.status).to.eq(200);
});
});

// await API register link
cy.wait('@linkResolverRegister').then((interception) => {
expect(interception?.response?.statusCode).to.eq(201);
cy.log('Completed: linkResolverRegister');
});

// Verify toast appears, using react-toastify
cy.get('.Toastify__toast')
.should('be.visible')
.and('contain', 'Action Successful');

// Validate localStorage
cy.window().then((win) => {
const rawData = win.localStorage.getItem('orchard_facility_dpps');
expect(rawData).to.not.be.null;
});
});
});
61 changes: 61 additions & 0 deletions cypress/e2e/simple_test/actorTesting.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
describe('Facility Links Test', () => {
ThanhDoDuy marked this conversation as resolved.
Show resolved Hide resolved
it('should visit the homepage and verify the facility links', () => {
// Visit the homepage
cy.visit('/');
// Verify the presence of the "CHERRIES SUPPLY CHAIN TRACEABILITY" text
cy.contains('h5', 'CHERRIES SUPPLY CHAIN TRACEABILITY').should('be.visible');
});

it('should verify all <a> tags from the second match the expected texts', () => {
// Danh sách các text mong đợi, tương ứng với từ thẻ <a> thứ 2 trở đi
ThanhDoDuy marked this conversation as resolved.
Show resolved Hide resolved
const expectedTexts = [
'Orchard Facility',
'Packhouse Facility',
'Fumigation and Freight Forwarding Facility',
'Airport Terminal Facility',
'Scanning',
'General features',
];

// Truy cập trang
cy.visit('/');

// Lấy tất cả các thẻ <a> (trừ thẻ đầu tiên)
cy.get('a').then(($aTags) => {
// Đảm bảo tổng số thẻ (trừ thẻ đầu) bằng với danh sách expectedTexts
expect($aTags.length - 1).to.equal(expectedTexts.length);

// Lặp qua từng thẻ từ index = 1 (thẻ thứ 2 trở đi)
$aTags.each((index, el) => {
if (index === 0) return; // Bỏ qua thẻ đầu tiên

// Lấy nội dung text của thẻ hiện tại
cy.wrap(el)
.invoke('text')
.then((text) => {
// So sánh text với giá trị tương ứng trong expectedTexts
expect(text.trim()).to.equal(expectedTexts[index - 1]); // Trừ đi 1 vì bỏ qua thẻ đầu tiên
});
});
});
});

describe('Facility Links Test', () => {
it('should visit the homepage and click on the "Orchard Facility" link', () => {
// Visit the homepage
cy.visit('/');

// Locate the Orchard Facility link by its href attribute and class
cy.get('a').eq(1).should('be.visible').and('not.be.disabled').click()

// Verify the URL to confirm navigation
cy.url().should('include', '/orchard-facility');
// Check if the Submit button appears after clicking
cy.get('a') // Adjust this selector if the button isn't of type submit
.eq(1)
.should('be.visible')
.and('not.be.disabled')
.click()
});
});
});
Loading
Loading