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 shipstation tests #2444

Merged
merged 7 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
194 changes: 148 additions & 46 deletions tests/pw/feature-map/feature-map.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tests/pw/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"site:reset": "NO_SETUP=false npm run site:setup && npm run env:setup",
"site:setup": "npx playwright test --project=local_site_setup --config=e2e.config.ts",
"env:setup": "npx playwright test --project=e2e_setup --config=e2e.config.ts",
"auth:setup": "NO_SETUP=true npx playwright test --project=auth_setup --config=e2e.config.ts",
"test:api": "npx playwright test --project=api_tests --config=api.config.ts",
"test:e2e": "npx playwright test --project=e2e_tests --config=e2e.config.ts",
"test:api:pro": "DOKAN_PRO=true npx playwright test --project=api_tests --config=api.config.ts",
Expand Down
16 changes: 13 additions & 3 deletions tests/pw/pages/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6545,16 +6545,26 @@ export const selector = {
shipStationText: '.dokan-settings-content h1',
visitStore: '//a[normalize-space()="Visit Store"]',

authenticationKey: '//label[normalize-space()="Authentication Key"]/..//code',
generateCredentials: 'button#dokan-shipstation-generate-credentials-btn',
generateSuccessMessage: '//div[@id="swal2-html-container" and normalize-space()="API credentials generated successfully."]',
revokeCredentials: 'button#dokan-shipstation-revoke-credentials-btn',
confirmRevoke: 'button.swal2-confirm',
revokeSuccessMessage: '//div[@id="swal2-html-container" and normalize-space()="API credentials revoked successfully."]',

credentials: {
authenticationKey: '//label[normalize-space()="Authentication Key"]/..//code',
consumerKey: '//label[normalize-space()="Consumer Key"]/..//code',
consumerSecret: '//label[normalize-space()="Consumer Secret"]/..//code',
},

selectedStatus: '//label[@for="dokan-shipstation-export-statuses"]/..//li[@class="select2-selection__choice"]',
exportOrderStatusesInput: '//label[normalize-space()="Export Order Statuses"]/..//span[@class="select2-selection select2-selection--multiple"]//input[@class="select2-search__field"]',
shippedOrderStatusDropdown: '.select2-selection__arrow',
shippedOrderStatusInput: '(//input[@class="select2-search__field"])[2]',
result: '.select2-results__option.select2-results__option--highlighted',

saveChanges: '#dokan-store-shipstation-form-submit',
saveSuccessMessage: '#swal2-html-container',
successOk: '.swal2-confirm',
saveSuccessMessage: '//div[@id="swal2-html-container" and normalize-space()="Settings saved successfully."]',
},

// social profile settings
Expand Down
35 changes: 35 additions & 0 deletions tests/pw/pages/shipstationPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Page } from '@playwright/test';
import { VendorPage } from '@pages/vendorPage';
import { selector } from '@pages/selectors';
import { data } from '@utils/testData';

// selectors
const settingsShipStation = selector.vendor.vShipStationSettings;

export class ShipStationPage extends VendorPage {
constructor(page: Page) {
super(page);
}

// generate shipStation credentials
async generateShipStationCredentials() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipStation);
await this.clickAndAcceptAndWaitForResponse(data.subUrls.api.dokan.shipStation, settingsShipStation.generateCredentials, 201);
await this.toBeVisible(settingsShipStation.generateSuccessMessage);

await this.toBeVisible(settingsShipStation.revokeCredentials);
await this.multipleElementVisible(settingsShipStation.credentials);
}

// revoke shipStation credentials
async revokeShipStationCredentials() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipStation);

await this.click(settingsShipStation.revokeCredentials);
await this.clickAndAcceptAndWaitForResponse(data.subUrls.api.dokan.shipStation, settingsShipStation.confirmRevoke);
await this.toBeVisible(settingsShipStation.revokeSuccessMessage);

await this.toBeVisible(settingsShipStation.generateCredentials);
await this.multipleElementNotVisible(settingsShipStation.credentials);
}
}
16 changes: 12 additions & 4 deletions tests/pw/pages/vendorAuctionsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,6 @@ export class AuctionsPage extends VendorPage {
await this.removeAttribute(auctionProductsVendor.auction.auctionEndDate, 'readonly');
await this.clearAndType(auctionProductsVendor.auction.auctionStartDate, generalOption.startDate);
await this.clearAndType(auctionProductsVendor.auction.auctionEndDate, generalOption.endDate);
await this.check(auctionProductsVendor.auction.enableAutomaticRelisting);
await this.clearAndType(auctionProductsVendor.auction.relistIfFailAfterNHours, generalOption.relistIfFailAfterNHours);
await this.clearAndType(auctionProductsVendor.auction.relistIfNotPaidAfterNHours, generalOption.relistIfNotPaidAfterNHours);
await this.clearAndType(auctionProductsVendor.auction.relistAuctionDurationInH, generalOption.relistAuctionDurationInH);

await this.saveProduct();

Expand All @@ -251,6 +247,18 @@ export class AuctionsPage extends VendorPage {
await this.toHaveValue(auctionProductsVendor.auction.buyItNowPrice, buyItNowPrice);
await this.toHaveValue(auctionProductsVendor.auction.auctionStartDate, generalOption.startDate);
await this.toHaveValue(auctionProductsVendor.auction.auctionEndDate, generalOption.endDate);
}

// add product Relist option
async addProductRelistingOption(productName: string, generalOption: product['auction']) {
await this.goToAuctionProductEditById(productName);
await this.check(auctionProductsVendor.auction.enableAutomaticRelisting);
await this.clearAndType(auctionProductsVendor.auction.relistIfFailAfterNHours, generalOption.relistIfFailAfterNHours);
await this.clearAndType(auctionProductsVendor.auction.relistIfNotPaidAfterNHours, generalOption.relistIfNotPaidAfterNHours);
await this.clearAndType(auctionProductsVendor.auction.relistAuctionDurationInH, generalOption.relistAuctionDurationInH);

await this.saveProduct();

await this.toBeChecked(auctionProductsVendor.auction.enableAutomaticRelisting);
await this.toHaveValue(auctionProductsVendor.auction.relistIfFailAfterNHours, generalOption.relistIfFailAfterNHours);
await this.toHaveValue(auctionProductsVendor.auction.relistIfNotPaidAfterNHours, generalOption.relistIfNotPaidAfterNHours);
Expand Down
36 changes: 21 additions & 15 deletions tests/pw/pages/vendorSettingsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,23 @@ export class VendorSettingsPage extends VendorPage {
await this.toBeVisible(settingsVendor.updateSettings);
}

// vendor shipstation render properly
async vendorShipstationSettingsRenderProperly() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipstation);
// vendor ShipStation render properly
async vendorShipStationSettingsRenderProperly() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipStation);

// shipStation text is visible
await this.toBeVisible(settingsShipStation.shipStationText);

// visit store link is visible
await this.toBeVisible(settingsShipStation.visitStore);

// authentication key is visible
await this.toBeVisible(settingsShipStation.authenticationKey);
const isCredentialsGenerated = await this.isVisible(settingsShipStation.revokeCredentials);

if (isCredentialsGenerated) {
await this.multipleElementVisible(settingsShipStation.credentials);
} else {
await this.toBeVisible(settingsShipStation.generateCredentials);
}

// export order statuses is visible
await this.toBeVisible(settingsShipStation.exportOrderStatusesInput);
Expand Down Expand Up @@ -438,26 +443,27 @@ export class VendorSettingsPage extends VendorPage {
await this.clearAndType(settingsVendor.minMax.maximumAmountToPlaceAnOrder, minMax.maximumAmount);
}

// vendor set Shipstation settings
// vendor set ShipStation settings
async setShipStation(shipStation: vendor['shipStation']): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipstation);
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipStation);

// export order statuses
const allStatus = await this.getMultipleElementTexts(settingsShipStation.selectedStatus);
const statusIsSelected = allStatus.includes('×' + shipStation.status);
const statusIsSelected = allStatus.includes(`×${shipStation.status}`);
if (!statusIsSelected) {
await this.clearAndType(settingsShipStation.exportOrderStatusesInput, shipStation.status);
await this.toContainText(settingsShipStation.result, shipStation.status);
await this.press(data.key.enter);
}

// await this.click(settingsShipStation.shippedOrderStatusDropdown);
// await this.clearAndType(settingsShipStation.shippedOrderStatusInput, shipStation.status);// todo: need to fix -> locator issue
// await this.toContainText(settingsShipStation.result, shipStation.status);
// await this.press(data.key.enter);
// shipped order status
await this.click(settingsShipStation.shippedOrderStatusDropdown);
await this.clearAndType(settingsShipStation.shippedOrderStatusInput, shipStation.status);
await this.toContainText(settingsShipStation.result, shipStation.status);
await this.press(data.key.enter);

await this.clickAndAcceptAndWaitForResponse(data.subUrls.ajax, settingsShipStation.saveChanges);
await this.toContainText(settingsShipStation.saveSuccessMessage, 'Your changes has been updated!');
await this.click(settingsShipStation.successOk);
await this.clickAndAcceptAndWaitForResponse(data.subUrls.api.dokan.shipStation, settingsShipStation.saveChanges, 201);
await this.toBeVisible(settingsShipStation.saveSuccessMessage);
}

// vendor set social profile settings
Expand Down
2 changes: 1 addition & 1 deletion tests/pw/pages/vendorShippingPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class VendorShippingPage extends VendorPage {
async vendorShippingSettingsRenderProperly() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.settingsShipping);

// shipstation text is visible
// ShipStation text is visible
await this.toBeVisible(vendorShipping.shippingSettingsText);

// visit store link is visible
Expand Down
69 changes: 69 additions & 0 deletions tests/pw/tests/api/shipstation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//COVERAGE_TAG: GET /dokan/v1/shipstation/credentials/(?P<id>[\d]+)
//COVERAGE_TAG: POST /dokan/v1/shipstation/credentials/create
//COVERAGE_TAG: DELETE /dokan/v1/shipstation/credentials/(?P<id>[\d]+)
//COVERAGE_TAG: GET /dokan/v1/shipstation/order-statuses
//COVERAGE_TAG: POST /dokan/v1/shipstation/order-statuses/(?P<id>[\d]+)
//COVERAGE_TAG: DELETE /dokan/v1/shipstation/order-statuses/(?P<id>[\d]+)

import { test, expect, request } from '@playwright/test';
import { ApiUtils } from '@utils/apiUtils';
import { endPoints } from '@utils/apiEndPoints';
import { payloads } from '@utils/payloads';
import { schemas } from '@utils/schemas';

const { VENDOR_ID } = process.env;

test.describe('ShipStation api test', () => {
test.skip(true, 'remove after pr is merged');
let apiUtils: ApiUtils;

test.beforeAll(async () => {
apiUtils = new ApiUtils(await request.newContext());
});

test.afterAll(async () => {
await apiUtils.dispose();
});

test('create ShipStation credential', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.post(endPoints.createShipStationCredential, { data: { vendor_id: VENDOR_ID } });
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationCredentialSchema);
});

test('get ShipStation credential', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.get(endPoints.getShipStationCredential(VENDOR_ID));
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationCredentialSchema);
});

test('delete ShipStation credential', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.delete(endPoints.deleteShipStationCredential(VENDOR_ID));
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationCredentialSchema);
});

test('create ShipStation order status settings', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.post(endPoints.createShipStationOrderStatusSettings, { data: { ...payloads.shipStationOrderStatusSettings, vendor_id: VENDOR_ID } });
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationOrderStatusSettingSchema);
});

test('get ShipStation order status settings', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.get(endPoints.getShipStationOrderStatusSettings(VENDOR_ID));
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationOrderStatusSettingSchema);
});

test('delete ShipStation order status settings', { tag: ['@pro'] }, async () => {
const [response, responseBody] = await apiUtils.delete(endPoints.deleteShipStationOrderStatusSettings(VENDOR_ID));
expect(response.ok()).toBeTruthy();
expect(responseBody).toBeTruthy();
expect(responseBody).toMatchSchema(schemas.shipStationSchema.shipStationOrderStatusSettingSchema);
});
});
9 changes: 9 additions & 0 deletions tests/pw/tests/e2e/productsDetailsAuction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ test.describe('Auction Product details functionality test', () => {
await vendor.addProductGeneralOption(productIdBasic, { ...data.product.auction, itemCondition: 'used', auctionType: 'reverse' });
});

test('vendor can enable product relist options', { tag: ['@pro', '@vendor'] }, async () => {
await vendor.addProductRelistingOption(productIdBasic, data.product.auction);
});

test('vendor can update product relist options', { tag: ['@pro', '@vendor'] }, async () => {
test.skip(true, 'not implemented yet');
await vendor.addProductGeneralOption(productIdFull, data.product.auction);
});
shashwatahalder01 marked this conversation as resolved.
Show resolved Hide resolved

// product inventory options

test('vendor can add auction product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => {
Expand Down
29 changes: 29 additions & 0 deletions tests/pw/tests/e2e/shipstation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { test, Page } from '@playwright/test';
import { ShipStationPage } from '@pages/shipStationPage';
import { data } from '@utils/testData';

test.describe('ShipStation test', () => {
test.skip(true, 'remove after pr is merged');
let vendor: ShipStationPage;
let vPage: Page;

test.beforeAll(async ({ browser }) => {
const vendorContext = await browser.newContext(data.auth.vendorAuth);
vPage = await vendorContext.newPage();
vendor = new ShipStationPage(vPage);
});

test.afterAll(async () => {
await vPage.close();
});

// vendor

test('vendor can generate ShipStation credentials', { tag: ['@pro', '@exploratory', '@vendor'] }, async () => {
await vendor.generateShipStationCredentials();
});

test('vendor can revoke ShipStation credentials', { tag: ['@pro', '@exploratory', '@vendor'] }, async () => {
await vendor.revokeShipStationCredentials();
});
});
7 changes: 4 additions & 3 deletions tests/pw/tests/e2e/vendorSettings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ test.describe('Vendor settings test', () => {
await vendor.vendorStoreSettingsRenderProperly();
});

test('vendor can view Shipstation settings menu page', { tag: ['@pro', '@exploratory', '@vendor'] }, async () => {
await vendor.vendorShipstationSettingsRenderProperly();
test('vendor can view ShipStation settings menu page', { tag: ['@pro', '@exploratory', '@vendor'] }, async () => {
await vendor.vendorShipStationSettingsRenderProperly();
});

test('vendor can view social profile settings menu page', { tag: ['@pro', '@exploratory', '@vendor'] }, async () => {
Expand Down Expand Up @@ -113,11 +113,12 @@ test.describe('Vendor settings test', () => {

test('vendor can set min-max settings', { tag: ['@pro', '@vendor'] }, async () => {
await vendor.setStoreSettings(data.vendor.vendorInfo, 'min-max');

// disable min-max
await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { enable_min_max_quantity: 'off', enable_min_max_amount: 'off' });
});

test('vendor can set shipStation settings', { tag: ['@pro', '@vendor'] }, async () => {
test('vendor can set ShipStation settings', { tag: ['@pro', '@vendor'] }, async () => {
await vendor.setShipStation(data.vendor.shipStation);
});

Expand Down
10 changes: 9 additions & 1 deletion tests/pw/utils/apiEndPoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ export const endPoints = {
updateVerificationRequest: (requestId: string) => `${SERVER_URL}/dokan/v1/verification-requests/${requestId}`,
deleteVerificationRequest: (requestId: string) => `${SERVER_URL}/dokan/v1/verification-requests/${requestId}`,

//commission
// commission
getCommission: `${SERVER_URL}/dokan/v1/commission`,

// shipping status
Expand All @@ -375,6 +375,14 @@ export const endPoints = {
getSingleShipment: (orderId: string, shipmentId: string) => `${SERVER_URL}/dokan/v1/shipping-status/orders/${orderId}/shipment/${shipmentId}`,
updateShipment: (orderId: string, shipmentId: string) => `${SERVER_URL}/dokan/v1/shipping-status/orders/${orderId}/shipment/${shipmentId}`,

// ShipStation
getShipStationCredential: (vendorId: string) => `${SERVER_URL}/dokan/v1/shipstation/credentials/${vendorId}`,
createShipStationCredential: `${SERVER_URL}/dokan/v1/shipstation/credentials/create`,
deleteShipStationCredential: (vendorId: string) => `${SERVER_URL}/dokan/v1/shipstation/credentials/${vendorId}`,
getShipStationOrderStatusSettings: (vendorId: string) => `${SERVER_URL}/dokan/v1/shipstation/order-statuses/${vendorId}`,
createShipStationOrderStatusSettings: `${SERVER_URL}/dokan/v1/shipstation/order-statuses`,
deleteShipStationOrderStatusSettings: (vendorId: string) => `${SERVER_URL}/dokan/v1/shipstation/order-statuses/${vendorId}`,

wc: {
// coupons
getAllCoupons: `${SERVER_URL}/wc/v3/coupons`,
Expand Down
24 changes: 24 additions & 0 deletions tests/pw/utils/apiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,30 @@
return [responseBody, orderId, shipmentId];
}

/**
* ShipStation methods
*/

shashwatahalder01 marked this conversation as resolved.
Show resolved Hide resolved
async createShipStationCredential(vendorId: string, auth?: auth): Promise<responseBody> {
const [, responseBody] = await this.post(endPoints.createShipStationCredential, { data: { vendor_id: vendorId }, headers: auth });
return responseBody;
}

async deleteShipStationCredential(vendorId: string, auth?: auth): Promise<responseBody> {
const [, responseBody] = await this.delete(endPoints.deleteShipStationCredential(vendorId), { headers: auth });
return responseBody;
}

async createShipStationOrderStatusSettings(payload: object, auth?: auth): Promise<responseBody> {
const [, responseBody] = await this.post(endPoints.createShipStationOrderStatusSettings, { data: payload, headers: auth });
return responseBody;
}

async deleteShipStationOrderStatusSettings(vendorId: string, auth?: auth): Promise<responseBody> {
const [, responseBody] = await this.delete(endPoints.deleteShipStationOrderStatusSettings(vendorId), { headers: auth });
return responseBody;
}

/**
* wp api methods
*/
Expand Down Expand Up @@ -2359,7 +2383,7 @@
// get system status
async getSystemStatus(auth?: auth): Promise<[responseBody, object]> {
const [, responseBody] = await this.get(endPoints.wc.getAllSystemStatus, { headers: auth });
const activePlugins = responseBody.active_plugins.map((a: { plugin: string; version: string }) => a.plugin.split('/')[0] + ' v' + a.version);

Check failure on line 2386 in tests/pw/utils/apiUtils.ts

View workflow job for this annotation

GitHub Actions / e2e_api tests

[site_setup] › _site.setup.ts:103:10 › site setup › get test environment info

2) [site_setup] › _site.setup.ts:103:10 › site setup › get test environment info ───────────────── TypeError: Cannot read properties of undefined (reading 'active_plugins') at ../../utils/apiUtils.ts:2386 2384 | async getSystemStatus(auth?: auth): Promise<[responseBody, object]> { 2385 | const [, responseBody] = await this.get(endPoints.wc.getAllSystemStatus, { headers: auth }); > 2386 | const activePlugins = responseBody.active_plugins.map((a: { plugin: string; version: string }) => a.plugin.split('/')[0] + ' v' + a.version); | ^ 2387 | activePlugins.sort(); 2388 | const compactInfo = { 2389 | os: 'OS: ' + (await this.getOsInfo()), at ApiUtils.getSystemStatus (/home/runner/work/dokan/dokan/tests/pw/utils/apiUtils.ts:2386:44) at /home/runner/work/dokan/dokan/tests/pw/tests/api/_site.setup.ts:104:32

Check failure on line 2386 in tests/pw/utils/apiUtils.ts

View workflow job for this annotation

GitHub Actions / e2e_api tests

[site_setup] › _site.setup.ts:103:10 › site setup › get test environment info

2) [site_setup] › _site.setup.ts:103:10 › site setup › get test environment info ───────────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── TypeError: Cannot read properties of undefined (reading 'active_plugins') at ../../utils/apiUtils.ts:2386 2384 | async getSystemStatus(auth?: auth): Promise<[responseBody, object]> { 2385 | const [, responseBody] = await this.get(endPoints.wc.getAllSystemStatus, { headers: auth }); > 2386 | const activePlugins = responseBody.active_plugins.map((a: { plugin: string; version: string }) => a.plugin.split('/')[0] + ' v' + a.version); | ^ 2387 | activePlugins.sort(); 2388 | const compactInfo = { 2389 | os: 'OS: ' + (await this.getOsInfo()), at ApiUtils.getSystemStatus (/home/runner/work/dokan/dokan/tests/pw/utils/apiUtils.ts:2386:44) at /home/runner/work/dokan/dokan/tests/pw/tests/api/_site.setup.ts:104:32
activePlugins.sort();
const compactInfo = {
os: 'OS: ' + (await this.getOsInfo()),
Expand Down
Loading
Loading