feat(attendance): add notification delivery and NFC security foundation
This commit is contained in:
@@ -153,6 +153,50 @@ async function main() {
|
||||
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,
|
||||
});
|
||||
@@ -517,6 +561,50 @@ async function main() {
|
||||
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,
|
||||
});
|
||||
@@ -871,6 +959,8 @@ async function main() {
|
||||
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),
|
||||
},
|
||||
@@ -878,6 +968,7 @@ async function main() {
|
||||
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', {
|
||||
@@ -950,10 +1041,13 @@ async function main() {
|
||||
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 requestedSwap = await apiCall(`/staff/shifts/${fixture.shifts.assigned.id}/request-swap`, {
|
||||
|
||||
Reference in New Issue
Block a user