import assert from 'node:assert/strict'; import { signInWithPassword } from '../src/services/identity-toolkit.js'; import { V2DemoFixture as fixture } from '../../command-api/scripts/v2-demo-fixture.mjs'; const unifiedBaseUrl = process.env.UNIFIED_API_BASE_URL || 'https://krow-api-v2-e3g6witsvq-uc.a.run.app'; const ownerEmail = process.env.V2_DEMO_OWNER_EMAIL || 'legendary.owner+v2@krowd.com'; const staffEmail = process.env.V2_DEMO_STAFF_EMAIL || 'ana.barista+v2@krowd.com'; const staffBenEmail = process.env.V2_DEMO_STAFF_BEN_EMAIL || 'ben.barista+v2@krowd.com'; const ownerPassword = process.env.V2_DEMO_OWNER_PASSWORD || 'Demo2026!'; const staffPassword = process.env.V2_DEMO_STAFF_PASSWORD || 'Demo2026!'; const staffBenPassword = process.env.V2_DEMO_STAFF_BEN_PASSWORD || 'Demo2026!'; function uniqueKey(prefix) { return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; } function isoDate(offsetDays = 0) { const value = new Date(Date.now() + (offsetDays * 24 * 60 * 60 * 1000)); return value.toISOString().slice(0, 10); } function isoTimestamp(offsetHours = 0) { return new Date(Date.now() + (offsetHours * 60 * 60 * 1000)).toISOString(); } function logStep(step, payload) { // eslint-disable-next-line no-console console.log(`[unified-smoke-v2] ${step}: ${JSON.stringify(payload)}`); } async function readJson(response) { const text = await response.text(); return text ? JSON.parse(text) : {}; } async function apiCall(path, { method = 'GET', token, idempotencyKey, body, expectedStatus = 200, allowFailure = false, } = {}) { const headers = {}; if (token) headers.Authorization = `Bearer ${token}`; if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey; if (body !== undefined) headers['Content-Type'] = 'application/json'; const response = await fetch(`${unifiedBaseUrl}${path}`, { method, headers, body: body === undefined ? undefined : JSON.stringify(body), }); const payload = await readJson(response); if (allowFailure) { return { statusCode: response.status, body: payload, }; } if (response.status !== expectedStatus) { throw new Error(`${method} ${path} expected ${expectedStatus}, got ${response.status}: ${JSON.stringify(payload)}`); } return payload; } async function uploadFile(path, token, { filename, contentType, content, fields = {}, expectedStatus = 200, }) { const form = new FormData(); for (const [key, value] of Object.entries(fields)) { form.set(key, value); } form.set( 'file', new File([content], filename, { type: contentType, }) ); const response = await fetch(`${unifiedBaseUrl}${path}`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, }, body: form, }); const payload = await readJson(response); if (response.status !== expectedStatus) { throw new Error(`POST ${path} expected ${expectedStatus}, got ${response.status}: ${JSON.stringify(payload)}`); } return payload; } async function finalizeVerifiedUpload({ token, uploadCategory, filename, contentType, content, finalizePath, finalizeMethod = 'PUT', verificationType, subjectId, rules = {}, finalizeBody = {}, }) { const uploaded = await uploadFile('/upload-file', token, { filename, contentType, content, fields: { visibility: 'private', category: uploadCategory, }, }); const signed = await apiCall('/create-signed-url', { method: 'POST', token, body: { fileUri: uploaded.fileUri, expiresInSeconds: 300, }, }); const verification = await apiCall('/verifications', { method: 'POST', token, body: { type: verificationType, subjectType: 'worker', subjectId, fileUri: uploaded.fileUri, rules, }, expectedStatus: 202, }); const finalized = await apiCall(finalizePath, { method: finalizeMethod, token, body: { ...finalizeBody, verificationId: verification.verificationId, fileUri: signed.signedUrl, photoUrl: signed.signedUrl, }, }); return { uploaded, signed, verification, finalized, }; } async function signInClient() { return apiCall('/auth/client/sign-in', { method: 'POST', body: { email: ownerEmail, password: ownerPassword, }, }); } async function signInStaff() { return signInWithPassword({ email: staffEmail, password: staffPassword, }); } async function signInStaffBen() { return signInWithPassword({ email: staffBenEmail, password: staffBenPassword, }); } async function main() { const reportWindow = `startDate=${encodeURIComponent(isoTimestamp(-24 * 14))}&endDate=${encodeURIComponent(isoTimestamp(24 * 14))}`; const ownerSession = await signInClient(); const staffAuth = await signInStaff(); const staffBenAuth = await signInStaffBen(); assert.ok(ownerSession.sessionToken); assert.ok(staffAuth.idToken); assert.ok(staffBenAuth.idToken); assert.equal(ownerSession.business.businessId, fixture.business.id); logStep('auth.client.sign-in.ok', { tenantId: ownerSession.tenant.tenantId, businessId: ownerSession.business.businessId, }); logStep('auth.staff.password-sign-in.ok', { uid: staffAuth.localId, email: staffEmail, }); logStep('auth.staff-b.password-sign-in.ok', { uid: staffBenAuth.localId, email: staffBenEmail, }); const authSession = await apiCall('/auth/session', { token: ownerSession.sessionToken, }); assert.equal(authSession.business.businessId, fixture.business.id); logStep('auth.session.ok', authSession); const staffPhoneStart = await apiCall('/auth/staff/phone/start', { method: 'POST', body: { phoneNumber: fixture.staff.ana.phone }, }); assert.equal(staffPhoneStart.mode, 'CLIENT_FIREBASE_SDK'); logStep('auth.staff.phone-start.ok', staffPhoneStart); const staffPhoneVerify = await apiCall('/auth/staff/phone/verify', { method: 'POST', body: { mode: 'sign-in', idToken: staffAuth.idToken, }, }); assert.equal(staffPhoneVerify.staff.staffId, fixture.staff.ana.id); logStep('auth.staff.phone-verify.ok', { staffId: staffPhoneVerify.staff.staffId, requiresProfileSetup: staffPhoneVerify.requiresProfileSetup, }); const clientSession = await apiCall('/client/session', { token: ownerSession.sessionToken, }); assert.equal(clientSession.business.businessId, fixture.business.id); logStep('client.session.ok', clientSession); const clientPushTokenPrimary = await apiCall('/client/devices/push-tokens', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('client-push-token-primary'), body: { provider: 'FCM', platform: 'IOS', pushToken: `smoke-client-primary-${Date.now()}-abcdefghijklmnop`, deviceId: 'smoke-client-iphone-15-pro', appVersion: '2.0.0-smoke', appBuild: '2000', locale: 'en-US', timezone: 'America/Los_Angeles', }, }); assert.ok(clientPushTokenPrimary.tokenId); logStep('client.push-token.register-primary.ok', clientPushTokenPrimary); const clientPushTokenCleanup = await apiCall('/client/devices/push-tokens', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('client-push-token-cleanup'), body: { provider: 'FCM', platform: 'ANDROID', pushToken: `smoke-client-cleanup-${Date.now()}-abcdefghijklmnop`, deviceId: 'smoke-client-pixel-9', appVersion: '2.0.0-smoke', appBuild: '2001', locale: 'en-US', timezone: 'America/Los_Angeles', }, }); assert.ok(clientPushTokenCleanup.tokenId); logStep('client.push-token.register-cleanup.ok', clientPushTokenCleanup); const clientPushTokenDeleted = await apiCall(`/client/devices/push-tokens?tokenId=${encodeURIComponent(clientPushTokenCleanup.tokenId)}&reason=SMOKE_CLEANUP`, { method: 'DELETE', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('client-push-token-delete'), }); assert.equal(clientPushTokenDeleted.removedCount, 1); logStep('client.push-token.delete.ok', clientPushTokenDeleted); const clientDashboard = await apiCall('/client/dashboard', { token: ownerSession.sessionToken, }); assert.equal(clientDashboard.businessId, fixture.business.id); logStep('client.dashboard.ok', { weeklySpendCents: clientDashboard.spending.weeklySpendCents, openPositionsToday: clientDashboard.coverage.openPositionsToday, }); const clientReorders = await apiCall('/client/reorders', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(clientReorders.items)); if (clientReorders.items[0]) { assert.equal(typeof clientReorders.items[0].hourlyRateCents, 'number'); assert.equal(typeof clientReorders.items[0].totalPriceCents, 'number'); } logStep('client.reorders.ok', { count: clientReorders.items.length }); const billingAccounts = await apiCall('/client/billing/accounts', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(billingAccounts.items)); logStep('client.billing.accounts.ok', { count: billingAccounts.items.length }); const pendingInvoices = await apiCall('/client/billing/invoices/pending', { token: ownerSession.sessionToken, }); assert.ok(pendingInvoices.items.length >= 1); const invoiceId = pendingInvoices.items[0].invoiceId; logStep('client.billing.pending-invoices.ok', { count: pendingInvoices.items.length, invoiceId }); const invoiceHistory = await apiCall('/client/billing/invoices/history', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(invoiceHistory.items)); logStep('client.billing.invoice-history.ok', { count: invoiceHistory.items.length }); const currentBill = await apiCall('/client/billing/current-bill', { token: ownerSession.sessionToken, }); assert.ok(typeof currentBill.currentBillCents === 'number'); logStep('client.billing.current-bill.ok', currentBill); const savings = await apiCall('/client/billing/savings', { token: ownerSession.sessionToken, }); assert.ok(typeof savings.savingsCents === 'number'); logStep('client.billing.savings.ok', savings); const spendBreakdown = await apiCall('/client/billing/spend-breakdown?period=month', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(spendBreakdown.items)); logStep('client.billing.spend-breakdown.ok', { count: spendBreakdown.items.length }); const coverage = await apiCall(`/client/coverage?date=${isoDate(0)}`, { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(coverage.items)); logStep('client.coverage.ok', { count: coverage.items.length }); const coverageStats = await apiCall(`/client/coverage/stats?date=${isoDate(0)}`, { token: ownerSession.sessionToken, }); assert.ok(typeof coverageStats.totalCoveragePercentage === 'number'); logStep('client.coverage.stats.ok', coverageStats); const coreTeam = await apiCall('/client/coverage/core-team', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(coreTeam.items)); logStep('client.coverage.core-team.ok', { count: coreTeam.items.length }); const dispatchTeams = await apiCall('/client/coverage/dispatch-teams', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(dispatchTeams.items)); assert.ok(dispatchTeams.items.length >= 2); logStep('client.coverage.dispatch-teams.ok', { count: dispatchTeams.items.length }); const coverageIncidentsBefore = await apiCall(`/client/coverage/incidents?${reportWindow}`, { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(coverageIncidentsBefore.items)); assert.ok(coverageIncidentsBefore.items.length >= 1); logStep('client.coverage.incidents-before.ok', { count: coverageIncidentsBefore.items.length }); const hubs = await apiCall('/client/hubs', { token: ownerSession.sessionToken, }); const seededHub = hubs.items.find((hub) => hub.hubId === fixture.clockPoint.id); assert.ok(seededHub); assert.equal(seededHub.clockInMode, fixture.clockPoint.defaultClockInMode); assert.equal(seededHub.allowClockInOverride, fixture.clockPoint.allowClockInOverride); logStep('client.hubs.ok', { count: hubs.items.length }); const costCenters = await apiCall('/client/cost-centers', { token: ownerSession.sessionToken, }); assert.ok(costCenters.items.length >= 1); logStep('client.cost-centers.ok', { count: costCenters.items.length }); const vendors = await apiCall('/client/vendors', { token: ownerSession.sessionToken, }); assert.ok(vendors.items.length >= 1); logStep('client.vendors.ok', { count: vendors.items.length }); const vendorRoles = await apiCall(`/client/vendors/${fixture.vendor.id}/roles`, { token: ownerSession.sessionToken, }); assert.ok(vendorRoles.items.length >= 1); logStep('client.vendor-roles.ok', { count: vendorRoles.items.length }); const hubManagers = await apiCall(`/client/hubs/${fixture.clockPoint.id}/managers`, { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(hubManagers.items)); logStep('client.hub-managers.ok', { count: hubManagers.items.length }); const teamMembers = await apiCall('/client/team-members', { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(teamMembers.items)); logStep('client.team-members.ok', { count: teamMembers.items.length }); const createdShiftManager = await apiCall('/client/shift-managers', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('create-shift-manager'), body: { hubId: fixture.clockPoint.id, email: `smoke.manager.${Date.now()}@krowd.com`, firstName: 'Smoke', lastName: 'Manager', phone: '+15550009999', }, }); assert.ok(createdShiftManager.businessMembershipId); assert.equal(createdShiftManager.membershipStatus, 'INVITED'); assert.ok(createdShiftManager.managerAssignmentId); logStep('client.shift-manager.create.ok', createdShiftManager); const teamMembersAfterCreate = await apiCall('/client/team-members', { token: ownerSession.sessionToken, }); assert.ok(teamMembersAfterCreate.items.some((item) => item.businessMembershipId === createdShiftManager.businessMembershipId)); logStep('client.team-members.after-create.ok', { count: teamMembersAfterCreate.items.length }); const viewedOrders = await apiCall(`/client/orders/view?${reportWindow}`, { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(viewedOrders.items)); if (viewedOrders.items[0]) { assert.ok(viewedOrders.items[0].clientName); assert.equal(typeof viewedOrders.items[0].hourlyRate, 'number'); } logStep('client.orders.view.ok', { count: viewedOrders.items.length }); const reorderPreview = await apiCall(`/client/orders/${fixture.orders.completed.id}/reorder-preview`, { token: ownerSession.sessionToken, }); assert.equal(reorderPreview.orderId, fixture.orders.completed.id); logStep('client.orders.reorder-preview.ok', reorderPreview); const reportSummary = await apiCall(`/client/reports/summary?${reportWindow}`, { token: ownerSession.sessionToken, }); assert.ok(typeof reportSummary.totalShifts === 'number'); logStep('client.reports.summary.ok', reportSummary); const dailyOps = await apiCall(`/client/reports/daily-ops?date=${isoDate(0)}`, { token: ownerSession.sessionToken, }); logStep('client.reports.daily-ops.ok', dailyOps); const spendReport = await apiCall(`/client/reports/spend?${reportWindow}`, { token: ownerSession.sessionToken, }); logStep('client.reports.spend.ok', spendReport); const coverageReport = await apiCall(`/client/reports/coverage?${reportWindow}`, { token: ownerSession.sessionToken, }); logStep('client.reports.coverage.ok', coverageReport); const forecastReport = await apiCall(`/client/reports/forecast?${reportWindow}`, { token: ownerSession.sessionToken, }); logStep('client.reports.forecast.ok', forecastReport); const performanceReport = await apiCall(`/client/reports/performance?${reportWindow}`, { token: ownerSession.sessionToken, }); logStep('client.reports.performance.ok', performanceReport); const noShowReport = await apiCall(`/client/reports/no-show?${reportWindow}`, { token: ownerSession.sessionToken, }); logStep('client.reports.no-show.ok', noShowReport); const createdHub = await apiCall('/client/hubs', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('create-hub'), body: { name: `Smoke Hub ${Date.now()}`, fullAddress: '500 Castro Street, Mountain View, CA', latitude: 37.3925, longitude: -122.0782, city: 'Mountain View', state: 'CA', country: 'US', zipCode: '94041', costCenterId: fixture.costCenters.cafeOps.id, geofenceRadiusMeters: 100, }, }); assert.ok(createdHub.hubId); logStep('client.hubs.create.ok', createdHub); const updatedHub = await apiCall(`/client/hubs/${createdHub.hubId}`, { method: 'PUT', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('update-hub'), body: { name: `${createdHub.name || 'Smoke Hub'} Updated`, geofenceRadiusMeters: 140, }, }); logStep('client.hubs.update.ok', updatedHub); const assignedHubManager = await apiCall(`/client/hubs/${createdHub.hubId}/managers`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('assign-hub-manager'), body: { managerUserId: fixture.users.operationsManager.id, }, }); logStep('client.hubs.assign-manager.ok', assignedHubManager); const assignedNfc = await apiCall(`/client/hubs/${createdHub.hubId}/assign-nfc`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('assign-hub-nfc'), body: { nfcTagId: `NFC-SMOKE-${Date.now()}`, }, }); logStep('client.hubs.assign-nfc.ok', assignedNfc); const deletedHub = await apiCall(`/client/hubs/${createdHub.hubId}`, { method: 'DELETE', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('delete-hub'), body: { reason: 'smoke cleanup', }, }); logStep('client.hubs.delete.ok', deletedHub); const disputedInvoice = await apiCall(`/client/billing/invoices/${invoiceId}/dispute`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('invoice-dispute'), body: { reason: 'Smoke dispute before approval', }, }); logStep('client.billing.invoice-dispute.ok', disputedInvoice); const approvedInvoice = await apiCall(`/client/billing/invoices/${invoiceId}/approve`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('invoice-approve'), body: {}, }); logStep('client.billing.invoice-approve.ok', approvedInvoice); const createdOneTimeOrder = await apiCall('/client/orders/one-time', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('order-one-time'), body: { hubId: fixture.clockPoint.id, vendorId: fixture.vendor.id, eventName: `Smoke One-Time ${Date.now()}`, orderDate: isoDate(3), serviceType: 'RESTAURANT', positions: [ { roleId: fixture.roles.barista.id, startTime: '08:00', endTime: '16:00', workerCount: 1, payRateCents: 2200, billRateCents: 3500, }, ], }, }); assert.ok(createdOneTimeOrder.orderId); logStep('client.orders.create-one-time.ok', createdOneTimeOrder); const createdRecurringOrder = await apiCall('/client/orders/recurring', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('order-recurring'), body: { hubId: fixture.clockPoint.id, vendorId: fixture.vendor.id, eventName: `Smoke Recurring ${Date.now()}`, startDate: isoDate(5), endDate: isoDate(10), recurrenceDays: [1, 3, 5], serviceType: 'RESTAURANT', positions: [ { roleId: fixture.roles.barista.id, startTime: '09:00', endTime: '15:00', workersNeeded: 1, payRateCents: 2300, billRateCents: 3600, }, ], }, }); assert.ok(createdRecurringOrder.orderId); logStep('client.orders.create-recurring.ok', createdRecurringOrder); const createdPermanentOrder = await apiCall('/client/orders/permanent', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('order-permanent'), body: { hubId: fixture.clockPoint.id, vendorId: fixture.vendor.id, eventName: `Smoke Permanent ${Date.now()}`, startDate: isoDate(7), daysOfWeek: [1, 2, 3, 4, 5], horizonDays: 14, serviceType: 'RESTAURANT', positions: [ { roleId: fixture.roles.barista.id, startTime: '07:00', endTime: '13:00', workersNeeded: 1, payRateCents: 2200, billRateCents: 3500, }, ], }, }); assert.ok(createdPermanentOrder.orderId); logStep('client.orders.create-permanent.ok', createdPermanentOrder); const editedOrderCopy = await apiCall(`/client/orders/${createdRecurringOrder.orderId}/edit`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('order-edit'), body: { eventName: `Edited Copy ${Date.now()}`, }, }); assert.ok(editedOrderCopy.orderId); assert.notEqual(editedOrderCopy.orderId, createdRecurringOrder.orderId); logStep('client.orders.edit-copy.ok', editedOrderCopy); const cancelledOrder = await apiCall(`/client/orders/${createdOneTimeOrder.orderId}/cancel`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('order-cancel'), body: { reason: 'Smoke cancel validation', }, }); assert.equal(cancelledOrder.futureOnly, true); logStep('client.orders.cancel.ok', cancelledOrder); const coverageReview = await apiCall('/client/coverage/reviews', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('coverage-review'), body: { staffId: fixture.staff.ana.id, assignmentId: fixture.assignments.completedAna.id, rating: 5, markAsFavorite: true, issueFlags: [], feedback: 'Smoke review', }, }); logStep('client.coverage.review.ok', coverageReview); const staffSession = await apiCall('/staff/session', { token: staffAuth.idToken, }); assert.equal(staffSession.staff.staffId, fixture.staff.ana.id); logStep('staff.session.ok', staffSession); const staffPushTokenPrimary = await apiCall('/staff/devices/push-tokens', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-push-token-primary'), body: { provider: 'FCM', platform: 'IOS', pushToken: `smoke-staff-primary-${Date.now()}-abcdefghijklmnop`, deviceId: 'smoke-staff-iphone-15-pro', appVersion: '2.0.0-smoke', appBuild: '2000', locale: 'en-US', timezone: 'America/Los_Angeles', }, }); assert.ok(staffPushTokenPrimary.tokenId); logStep('staff.push-token.register-primary.ok', staffPushTokenPrimary); const staffPushTokenCleanup = await apiCall('/staff/devices/push-tokens', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-push-token-cleanup'), body: { provider: 'FCM', platform: 'ANDROID', pushToken: `smoke-staff-cleanup-${Date.now()}-abcdefghijklmnop`, deviceId: 'smoke-staff-pixel-9', appVersion: '2.0.0-smoke', appBuild: '2001', locale: 'en-US', timezone: 'America/Los_Angeles', }, }); assert.ok(staffPushTokenCleanup.tokenId); logStep('staff.push-token.register-cleanup.ok', staffPushTokenCleanup); const staffPushTokenDeleted = await apiCall(`/staff/devices/push-tokens?tokenId=${encodeURIComponent(staffPushTokenCleanup.tokenId)}&reason=SMOKE_CLEANUP`, { method: 'DELETE', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-push-token-delete'), }); assert.equal(staffPushTokenDeleted.removedCount, 1); logStep('staff.push-token.delete.ok', staffPushTokenDeleted); const staffDashboard = await apiCall('/staff/dashboard', { token: staffAuth.idToken, }); assert.ok(Array.isArray(staffDashboard.recommendedShifts)); if (staffDashboard.todaysShifts[0]) { assert.ok(staffDashboard.todaysShifts[0].clientName); assert.equal(typeof staffDashboard.todaysShifts[0].totalRate, 'number'); } if (staffDashboard.recommendedShifts[0]) { assert.ok(staffDashboard.recommendedShifts[0].clientName); assert.equal(typeof staffDashboard.recommendedShifts[0].totalRate, 'number'); } logStep('staff.dashboard.ok', { todaysShifts: staffDashboard.todaysShifts.length, recommendedShifts: staffDashboard.recommendedShifts.length, }); const staffProfileCompletion = await apiCall('/staff/profile-completion', { token: staffAuth.idToken, }); logStep('staff.profile-completion.ok', staffProfileCompletion); const staffAvailability = await apiCall('/staff/availability', { token: staffAuth.idToken, }); assert.ok(Array.isArray(staffAvailability.items)); logStep('staff.availability.ok', { count: staffAvailability.items.length }); const todaysShifts = await apiCall('/staff/clock-in/shifts/today', { token: staffAuth.idToken, }); assert.ok(Array.isArray(todaysShifts.items)); const assignedTodayShift = todaysShifts.items.find((shift) => shift.shiftId === fixture.shifts.assigned.id); assert.ok(assignedTodayShift); assert.equal(assignedTodayShift.clientName, fixture.business.name); assert.equal(typeof assignedTodayShift.hourlyRate, 'number'); assert.equal(typeof assignedTodayShift.latitude, 'number'); assert.equal(typeof assignedTodayShift.longitude, 'number'); assert.equal(assignedTodayShift.clockInMode, fixture.shifts.assigned.clockInMode); assert.equal(assignedTodayShift.allowClockInOverride, fixture.shifts.assigned.allowClockInOverride); logStep('staff.clock-in.shifts-today.ok', { count: todaysShifts.items.length }); const attendanceStatusBefore = await apiCall('/staff/clock-in/status', { token: staffAuth.idToken, }); logStep('staff.clock-in.status-before.ok', attendanceStatusBefore); const paymentsSummary = await apiCall('/staff/payments/summary?period=month', { token: staffAuth.idToken, }); logStep('staff.payments.summary.ok', paymentsSummary); const paymentsHistory = await apiCall('/staff/payments/history?period=month', { token: staffAuth.idToken, }); assert.ok(Array.isArray(paymentsHistory.items)); logStep('staff.payments.history.ok', { count: paymentsHistory.items.length }); const paymentsChart = await apiCall('/staff/payments/chart?period=month', { token: staffAuth.idToken, }); assert.ok(Array.isArray(paymentsChart.items)); logStep('staff.payments.chart.ok', { count: paymentsChart.items.length }); const assignedShifts = await apiCall(`/staff/shifts/assigned?${reportWindow}`, { token: staffAuth.idToken, }); assert.ok(Array.isArray(assignedShifts.items)); logStep('staff.shifts.assigned.ok', { count: assignedShifts.items.length }); const openShifts = await apiCall('/staff/shifts/open', { token: staffAuth.idToken, }); const openShift = openShifts.items.find((shift) => shift.shiftId === fixture.shifts.available.id) || openShifts.items[0]; const blockedApplyCandidate = openShifts.items.find((shift) => shift.shiftId !== openShift.shiftId); assert.ok(openShift); assert.ok(blockedApplyCandidate); logStep('staff.shifts.open.ok', { count: openShifts.items.length }); const pendingShifts = await apiCall('/staff/shifts/pending', { token: staffAuth.idToken, }); const pendingShift = pendingShifts.items.find((item) => item.shiftId === fixture.shifts.available.id) || pendingShifts.items[0]; assert.ok(pendingShift); logStep('staff.shifts.pending.ok', { count: pendingShifts.items.length }); const cancelledShifts = await apiCall('/staff/shifts/cancelled', { token: staffAuth.idToken, }); assert.ok(Array.isArray(cancelledShifts.items)); logStep('staff.shifts.cancelled.ok', { count: cancelledShifts.items.length }); const completedShifts = await apiCall('/staff/shifts/completed', { token: staffAuth.idToken, }); assert.ok(Array.isArray(completedShifts.items)); if (completedShifts.items[0]) { assert.ok(completedShifts.items[0].clientName); assert.ok(completedShifts.items[0].date); assert.ok(completedShifts.items[0].startTime); assert.ok(completedShifts.items[0].endTime); assert.equal(typeof completedShifts.items[0].hourlyRate, 'number'); assert.equal(typeof completedShifts.items[0].totalRate, 'number'); } logStep('staff.shifts.completed.ok', { count: completedShifts.items.length }); const shiftDetail = await apiCall(`/staff/shifts/${openShift.shiftId}`, { token: staffAuth.idToken, }); assert.equal(shiftDetail.shiftId, openShift.shiftId); assert.equal(typeof shiftDetail.latitude, 'number'); assert.equal(typeof shiftDetail.longitude, 'number'); logStep('staff.shifts.detail.ok', shiftDetail); const profileSections = await apiCall('/staff/profile/sections', { token: staffAuth.idToken, }); logStep('staff.profile.sections.ok', profileSections); const personalInfo = await apiCall('/staff/profile/personal-info', { token: staffAuth.idToken, }); logStep('staff.profile.personal-info.ok', personalInfo); const industries = await apiCall('/staff/profile/industries', { token: staffAuth.idToken, }); assert.ok(Array.isArray(industries.items)); logStep('staff.profile.industries.ok', industries); const skills = await apiCall('/staff/profile/skills', { token: staffAuth.idToken, }); assert.ok(Array.isArray(skills.items)); logStep('staff.profile.skills.ok', skills); const profileDocumentsBefore = await apiCall('/staff/profile/documents', { token: staffAuth.idToken, }); assert.ok(Array.isArray(profileDocumentsBefore.items)); assert.ok(profileDocumentsBefore.items.every((item) => item.documentType !== 'ATTIRE')); logStep('staff.profile.documents-before.ok', { count: profileDocumentsBefore.items.length }); const attireChecklistBefore = await apiCall('/staff/profile/attire', { token: staffAuth.idToken, }); assert.ok(Array.isArray(attireChecklistBefore.items)); logStep('staff.profile.attire-before.ok', { count: attireChecklistBefore.items.length }); const taxForms = await apiCall('/staff/profile/tax-forms', { token: staffAuth.idToken, }); assert.ok(Array.isArray(taxForms.items)); logStep('staff.profile.tax-forms.ok', { count: taxForms.items.length }); const emergencyContactsBefore = await apiCall('/staff/profile/emergency-contacts', { token: staffAuth.idToken, }); assert.ok(Array.isArray(emergencyContactsBefore.items)); logStep('staff.profile.emergency-contacts-before.ok', { count: emergencyContactsBefore.items.length }); const certificatesBefore = await apiCall('/staff/profile/certificates', { token: staffAuth.idToken, }); assert.ok(Array.isArray(certificatesBefore.items)); logStep('staff.profile.certificates-before.ok', { count: certificatesBefore.items.length }); const bankAccountsBefore = await apiCall('/staff/profile/bank-accounts', { token: staffAuth.idToken, }); assert.ok(Array.isArray(bankAccountsBefore.items)); logStep('staff.profile.bank-accounts-before.ok', { count: bankAccountsBefore.items.length }); const benefits = await apiCall('/staff/profile/benefits', { token: staffAuth.idToken, }); assert.ok(Array.isArray(benefits.items)); logStep('staff.profile.benefits.ok', { count: benefits.items.length }); const benefitHistory = await apiCall('/staff/profile/benefits/history?limit=10', { token: staffAuth.idToken, }); assert.ok(Array.isArray(benefitHistory.items)); assert.ok(benefitHistory.items.length >= 1); logStep('staff.profile.benefits.history.ok', { count: benefitHistory.items.length }); const timeCard = await apiCall(`/staff/profile/time-card?month=${new Date().getUTCMonth() + 1}&year=${new Date().getUTCFullYear()}`, { token: staffAuth.idToken, }); assert.ok(Array.isArray(timeCard.items)); logStep('staff.profile.time-card.ok', { count: timeCard.items.length }); const privacyBefore = await apiCall('/staff/profile/privacy', { token: staffAuth.idToken, }); logStep('staff.profile.privacy-before.ok', privacyBefore); const faqs = await apiCall('/staff/faqs'); assert.ok(Array.isArray(faqs.items)); logStep('staff.faqs.ok', { count: faqs.items.length }); const faqSearch = await apiCall('/staff/faqs/search?q=payments'); assert.ok(Array.isArray(faqSearch.items)); logStep('staff.faqs.search.ok', { count: faqSearch.items.length }); const updatedAvailability = await apiCall('/staff/availability', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-availability'), body: { dayOfWeek: 2, availabilityStatus: 'PARTIAL', slots: [{ start: '10:00', end: '18:00' }], }, }); logStep('staff.availability.update.ok', updatedAvailability); const quickSetAvailability = await apiCall('/staff/availability/quick-set', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-availability-quick-set'), body: { quickSetType: 'weekdays', startDate: isoTimestamp(0), endDate: isoTimestamp(24 * 7), }, }); logStep('staff.availability.quick-set.ok', quickSetAvailability); const personalInfoUpdate = await apiCall('/staff/profile/personal-info', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-personal-info'), body: { firstName: 'Ana', lastName: 'Barista', bio: 'Smoke-tested staff bio', preferredLocations: [ { label: 'Mountain View', city: 'Mountain View', latitude: fixture.clockPoint.latitude, longitude: fixture.clockPoint.longitude, radiusMiles: 20, }, ], phone: fixture.staff.ana.phone, email: staffEmail, }, }); logStep('staff.profile.personal-info.update.ok', personalInfoUpdate); const experienceUpdate = await apiCall('/staff/profile/experience', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-experience'), body: { industries: ['CATERING', 'CAFE'], skills: ['BARISTA', 'CUSTOMER_SERVICE'], primaryRole: 'BARISTA', }, }); logStep('staff.profile.experience.update.ok', experienceUpdate); const locationUpdate = await apiCall('/staff/profile/locations', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-locations'), body: { preferredLocations: [ { label: 'Mountain View', city: 'Mountain View', latitude: fixture.clockPoint.latitude, longitude: fixture.clockPoint.longitude, radiusMiles: 25, }, ], maxDistanceMiles: 25, }, }); logStep('staff.profile.locations.update.ok', locationUpdate); const createdEmergencyContact = await apiCall('/staff/profile/emergency-contacts', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-emergency-create'), body: { fullName: 'Smoke Contact', phone: '+15550009999', relationshipType: 'Sibling', isPrimary: false, }, }); assert.ok(createdEmergencyContact.contactId); logStep('staff.profile.emergency-contact.create.ok', createdEmergencyContact); const updatedEmergencyContact = await apiCall(`/staff/profile/emergency-contacts/${createdEmergencyContact.contactId}`, { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-emergency-update'), body: { fullName: 'Smoke Contact Updated', relationshipType: 'Brother', }, }); logStep('staff.profile.emergency-contact.update.ok', updatedEmergencyContact); const savedW4Draft = await apiCall('/staff/profile/tax-forms/w4', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-tax-w4-draft'), body: { fields: { filingStatus: 'single', }, }, }); logStep('staff.profile.tax-form.w4-draft.ok', savedW4Draft); const submittedI9 = await apiCall('/staff/profile/tax-forms/i9/submit', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-tax-i9-submit'), body: { fields: { section1Complete: true, }, }, }); logStep('staff.profile.tax-form.i9-submit.ok', submittedI9); const addedBankAccount = await apiCall('/staff/profile/bank-accounts', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-bank-account'), body: { bankName: 'Demo Credit Union', accountNumber: '1234567890', routingNumber: '021000021', accountType: 'checking', }, }); logStep('staff.profile.bank-account.add.ok', addedBankAccount); const updatedPrivacy = await apiCall('/staff/profile/privacy', { method: 'PUT', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-privacy'), body: { profileVisible: true, }, }); logStep('staff.profile.privacy.update.ok', updatedPrivacy); const appliedShift = await apiCall(`/staff/shifts/${openShift.shiftId}/apply`, { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-shift-apply'), body: { roleId: fixture.shiftRoles.availableBarista.id, }, }); logStep('staff.shifts.apply.ok', appliedShift); const acceptedShift = await apiCall(`/staff/shifts/${fixture.shifts.assigned.id}/accept`, { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-shift-accept'), body: {}, }); logStep('staff.shifts.accept.ok', acceptedShift); const clockIn = await apiCall('/staff/clock-in', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-clock-in'), body: { shiftId: fixture.shifts.assigned.id, sourceType: 'GEO', deviceId: 'smoke-iphone-15-pro', latitude: fixture.clockPoint.latitude + 0.0075, longitude: fixture.clockPoint.longitude + 0.0075, accuracyMeters: 8, proofNonce: uniqueKey('geo-proof-clock-in'), proofTimestamp: isoTimestamp(0), overrideReason: 'Parking garage entrance is outside the marked hub geofence', capturedAt: isoTimestamp(0), }, }); assert.equal(clockIn.validationStatus, 'FLAGGED'); assert.equal(clockIn.effectiveClockInMode, fixture.shifts.assigned.clockInMode); assert.equal(clockIn.overrideUsed, true); assert.ok(clockIn.securityProofId); logStep('staff.clock-in.ok', clockIn); const attendanceStatusAfterClockIn = await apiCall('/staff/clock-in/status', { token: staffAuth.idToken, }); logStep('staff.clock-in.status-after.ok', attendanceStatusAfterClockIn); const locationStreamBatch = await apiCall('/staff/location-streams', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-location-stream'), body: { shiftId: fixture.shifts.assigned.id, sourceType: 'GEO', deviceId: 'smoke-iphone-15-pro', points: [ { capturedAt: isoTimestamp(0.05), latitude: fixture.clockPoint.latitude, longitude: fixture.clockPoint.longitude, accuracyMeters: 12, }, { capturedAt: isoTimestamp(0.1), latitude: fixture.clockPoint.latitude + 0.008, longitude: fixture.clockPoint.longitude + 0.008, accuracyMeters: 20, }, { capturedAt: isoTimestamp(0.15), accuracyMeters: 25, }, ], metadata: { source: 'live-smoke-v2-unified', }, }, }); assert.ok(locationStreamBatch.batchId); assert.ok(locationStreamBatch.incidentIds.length >= 1); logStep('staff.location-streams.ok', locationStreamBatch); const coverageIncidentsAfter = await apiCall(`/client/coverage/incidents?${reportWindow}`, { token: ownerSession.sessionToken, }); assert.ok(coverageIncidentsAfter.items.length > coverageIncidentsBefore.items.length); logStep('client.coverage.incidents-after.ok', { count: coverageIncidentsAfter.items.length }); const cancelledLateWorker = await apiCall(`/client/coverage/late-workers/${fixture.assignments.noShowAna.id}/cancel`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('client-late-worker-cancel'), body: { reason: 'Smoke cancellation for a confirmed late worker', }, }); assert.equal(cancelledLateWorker.assignmentId, fixture.assignments.noShowAna.id); assert.equal(cancelledLateWorker.status, 'CANCELLED'); assert.equal(cancelledLateWorker.replacementSearchTriggered, true); logStep('client.coverage.late-worker-cancel.ok', cancelledLateWorker); const clockOut = await apiCall('/staff/clock-out', { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-clock-out'), body: { shiftId: fixture.shifts.assigned.id, sourceType: 'GEO', deviceId: 'smoke-iphone-15-pro', latitude: fixture.clockPoint.latitude, longitude: fixture.clockPoint.longitude, accuracyMeters: 10, proofNonce: uniqueKey('geo-proof-clock-out'), proofTimestamp: isoTimestamp(1), breakMinutes: 30, capturedAt: isoTimestamp(1), }, }); assert.ok(clockOut.securityProofId); logStep('staff.clock-out.ok', clockOut); const submittedCompletedShift = await apiCall(`/staff/shifts/${fixture.shifts.assigned.id}/submit-for-approval`, { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-shift-submit-approval'), body: { note: 'Smoke approval submission', }, }); assert.equal(submittedCompletedShift.submitted, true); logStep('staff.shifts.submit-for-approval.ok', submittedCompletedShift); const requestedSwap = await apiCall(`/staff/shifts/${fixture.shifts.swapEligible.id}/request-swap`, { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-shift-swap'), body: { reason: 'Smoke swap request', }, }); logStep('staff.shifts.request-swap.ok', requestedSwap); const benOpenShifts = await apiCall('/staff/shifts/open?limit=10', { token: staffBenAuth.idToken, }); const benSwapShift = benOpenShifts.items.find((item) => item.shiftId === fixture.shifts.swapEligible.id); assert.ok(benSwapShift); assert.equal(benSwapShift.swapRequestId, requestedSwap.swapRequestId); assert.equal(benSwapShift.dispatchTeam, 'CERTIFIED_LOCATION'); logStep('staff-b.shifts.open-swap.ok', benSwapShift); const dispatchCandidates = await apiCall(`/client/coverage/dispatch-candidates?shiftId=${fixture.shifts.swapEligible.id}&roleId=${fixture.shiftRoles.swapEligibleBarista.id}`, { token: ownerSession.sessionToken, }); assert.ok(Array.isArray(dispatchCandidates.items)); assert.ok(dispatchCandidates.items.length >= 1); assert.equal(dispatchCandidates.items[0].staffId, fixture.staff.ben.id); logStep('client.coverage.dispatch-candidates.ok', { count: dispatchCandidates.items.length }); const benSwapApplication = await apiCall(`/staff/shifts/${fixture.shifts.swapEligible.id}/apply`, { method: 'POST', token: staffBenAuth.idToken, idempotencyKey: uniqueKey('staff-b-shift-swap-apply'), body: { roleId: fixture.shiftRoles.swapEligibleBarista.id, }, }); assert.ok(benSwapApplication.applicationId); logStep('staff-b.shifts.apply-swap.ok', benSwapApplication); const swapRequests = await apiCall('/client/coverage/swap-requests?status=OPEN', { token: ownerSession.sessionToken, }); const openSwapRequest = swapRequests.items.find((item) => item.swapRequestId === requestedSwap.swapRequestId); assert.ok(openSwapRequest); assert.ok(openSwapRequest.candidates.some((candidate) => candidate.staffId === fixture.staff.ben.id)); logStep('client.coverage.swap-requests.ok', { count: swapRequests.items.length }); const resolvedSwap = await apiCall(`/client/coverage/swap-requests/${requestedSwap.swapRequestId}/resolve`, { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('client-swap-resolve'), body: { applicationId: benSwapApplication.applicationId, note: 'Smoke resolved swap request', }, }); assert.equal(resolvedSwap.status, 'RESOLVED'); logStep('client.coverage.swap-resolve.ok', resolvedSwap); const blockedReview = await apiCall('/client/coverage/reviews', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('coverage-block'), body: { staffId: fixture.staff.ana.id, assignmentId: fixture.assignments.completedAna.id, rating: 2, markAsBlocked: true, markAsFavorite: false, issueFlags: ['LATE_CLOCK_IN'], feedback: 'Smoke blocked staff test', }, }); assert.equal(blockedReview.markAsBlocked, true); logStep('client.coverage.block.ok', blockedReview); const blockedStaff = await apiCall('/client/coverage/blocked-staff', { token: ownerSession.sessionToken, }); assert.ok(blockedStaff.items.some((item) => item.staffId === fixture.staff.ana.id)); logStep('client.coverage.blocked-staff.ok', { count: blockedStaff.items.length }); const blockedApplyAttempt = await apiCall(`/staff/shifts/${blockedApplyCandidate.shiftId}/apply`, { method: 'POST', token: staffAuth.idToken, idempotencyKey: uniqueKey('staff-shift-apply-blocked'), body: { roleId: blockedApplyCandidate.roleId, }, allowFailure: true, }); assert.equal(blockedApplyAttempt.statusCode, 409); assert.equal(blockedApplyAttempt.body?.code, 'STAFF_BLOCKED'); logStep('staff.shifts.apply-blocked.ok', blockedApplyAttempt.body); const unblockedReview = await apiCall('/client/coverage/reviews', { method: 'POST', token: ownerSession.sessionToken, idempotencyKey: uniqueKey('coverage-unblock'), body: { staffId: fixture.staff.ana.id, assignmentId: fixture.assignments.completedAna.id, rating: 5, markAsBlocked: false, markAsFavorite: true, issueFlags: [], feedback: 'Smoke unblock cleanup', }, }); assert.equal(unblockedReview.markAsBlocked, false); logStep('client.coverage.unblock.ok', unblockedReview); const uploadedProfilePhoto = await uploadFile('/staff/profile/photo', staffAuth.idToken, { filename: 'profile-photo.jpg', contentType: 'image/jpeg', content: Buffer.from('fake-profile-photo'), }); assert.ok(uploadedProfilePhoto.fileUri); logStep('staff.profile.photo.upload.ok', uploadedProfilePhoto); const uploadedGovId = await finalizeVerifiedUpload({ token: staffAuth.idToken, uploadCategory: 'staff-document', filename: 'government-id.jpg', contentType: 'image/jpeg', content: Buffer.from('fake-government-id'), finalizePath: `/staff/profile/documents/${fixture.documents.governmentId.id}/upload`, finalizeMethod: 'PUT', verificationType: 'government_id', subjectId: fixture.documents.governmentId.id, rules: { documentId: fixture.documents.governmentId.id, }, }); assert.equal(uploadedGovId.finalized.documentId, fixture.documents.governmentId.id); logStep('staff.profile.document.upload.ok', uploadedGovId.finalized); const uploadedAttire = await finalizeVerifiedUpload({ token: staffAuth.idToken, uploadCategory: 'staff-attire', filename: 'black-shirt.jpg', contentType: 'image/jpeg', content: Buffer.from('fake-black-shirt'), finalizePath: `/staff/profile/attire/${fixture.documents.attireBlackShirt.id}/upload`, finalizeMethod: 'PUT', verificationType: 'attire', subjectId: fixture.documents.attireBlackShirt.id, rules: { dressCode: 'Black shirt', }, }); assert.equal(uploadedAttire.finalized.documentId, fixture.documents.attireBlackShirt.id); logStep('staff.profile.attire.upload.ok', uploadedAttire.finalized); const certificateType = `ALCOHOL_SERVICE_${Date.now()}`; const uploadedCertificate = await finalizeVerifiedUpload({ token: staffAuth.idToken, uploadCategory: 'staff-certificate', filename: 'certificate.pdf', contentType: 'application/pdf', content: Buffer.from('fake-certificate'), finalizePath: '/staff/profile/certificates', finalizeMethod: 'POST', verificationType: 'certification', subjectId: certificateType, rules: { certificateName: 'Alcohol Service Permit', certificateIssuer: 'Demo Issuer', }, finalizeBody: { certificateType, name: 'Alcohol Service Permit', issuer: 'Demo Issuer', }, }); assert.equal(uploadedCertificate.finalized.certificateType, certificateType); logStep('staff.profile.certificate.upload.ok', uploadedCertificate.finalized); const profileDocumentsAfter = await apiCall('/staff/profile/documents', { token: staffAuth.idToken, }); assert.ok(profileDocumentsAfter.items.some((item) => item.documentId === fixture.documents.governmentId.id)); logStep('staff.profile.documents-after.ok', { count: profileDocumentsAfter.items.length }); const certificatesAfter = await apiCall('/staff/profile/certificates', { token: staffAuth.idToken, }); assert.ok(certificatesAfter.items.some((item) => item.certificateType === certificateType)); logStep('staff.profile.certificates-after.ok', { count: certificatesAfter.items.length }); const deletedCertificate = await apiCall(`/staff/profile/certificates/${certificateType}`, { method: 'DELETE', token: staffAuth.idToken, expectedStatus: 200, }); logStep('staff.profile.certificate.delete.ok', deletedCertificate); const clientSignOut = await apiCall('/auth/client/sign-out', { method: 'POST', token: ownerSession.sessionToken, }); logStep('auth.client.sign-out.ok', clientSignOut); const staffSignOut = await apiCall('/auth/staff/sign-out', { method: 'POST', token: staffAuth.idToken, }); logStep('auth.staff.sign-out.ok', staffSignOut); // eslint-disable-next-line no-console console.log('LIVE_SMOKE_V2_UNIFIED_OK'); } main().catch((error) => { // eslint-disable-next-line no-console console.error(error); process.exit(1); });