• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stores-com / bloodhound / 31017787024

05 Aug 2026 02:56PM UTC coverage: 88.0% (+0.5%) from 87.506%
31017787024

push

github

web-flow
Merge pull request #187 from stores-com/promise-carriers

Convert every carrier from callbacks to async/await

317 of 372 branches covered (85.22%)

Branch coverage included in aggregate %.

640 of 694 new or added lines in 11 files covered. (92.22%)

4 existing lines in 3 files now uncovered.

1487 of 1678 relevant lines covered (88.62%)

18.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.53
/carriers/amazon.js
1
const HttpError = require('@stores.com/http-error');
12✔
2

12✔
3
// These event codes indicate the shipment was delivered
12✔
4
const DELIVERED_EVENT_CODES = ['Delivered'];
12✔
5

12✔
6
// These event codes indicate the shipment is in the carrier's network
12✔
7
const SHIPPED_EVENT_CODES = ['PickupDone', 'Received', 'InTransit', 'Departed', 'ArrivedAtSortCenter'];
12✔
8

12✔
9
function Amazon() {
51✔
10
    // Helper function to convert Amazon event codes to readable descriptions
51✔
11
    const parseEventDescription = (eventCode, statusSummary) => {
51✔
12
        const eventMap = {
5✔
13
            'ArrivedAtDeliveryCenter': 'Arrived at delivery center',
5✔
14
            'ArrivedAtSortCenter': 'Arrived at sort center',
5✔
15
            'AttemptFail': 'Delivery attempt failed',
5✔
16
            'CreationConfirmed': 'Shipping label created',
5✔
17
            'Delivered': 'Package delivered',
5✔
18
            'DeliveryAttempted': 'Delivery attempted',
5✔
19
            'Departed': 'Departed facility',
5✔
20
            'Exception': 'Exception occurred',
5✔
21
            'Held': 'Package held',
5✔
22
            'InTransit': 'Package in transit',
5✔
23
            'InTransitToCustomer': 'In transit to customer',
5✔
24
            'LabelCreated': 'Shipping label created',
5✔
25
            'OutForDelivery': 'Out for delivery',
5✔
26
            'OutForReturn': 'Out for return',
5✔
27
            'PickupDone': 'Package picked up',
5✔
28
            'Received': 'Package received at facility',
5✔
29
            'Refused': 'Package refused',
5✔
30
            'Returned': 'Package returned',
5✔
31
            'ReturnReceived': 'Return received',
5✔
32
            'Sorted': 'Package sorted',
5✔
33
            'Transferred': 'Package transferred',
5✔
34
            'Undeliverable': 'Package undeliverable'
5✔
35
        };
5✔
36

5✔
37
        // Use status summary if available, otherwise fall back to event code mapping
5✔
38
        if (statusSummary && statusSummary.localisedStringId) {
5✔
39
            // Convert localized string IDs to readable text
5✔
40
            const summaryMap = {
5✔
41
                'swa_rex_arrived_at_sort_center': 'Arrived at sort center',
5✔
42
                'swa_rex_delivered': 'Package delivered',
5✔
43
                'swa_rex_detail_arrived_at_delivery_Center': 'Arrived at delivery center',
5✔
44
                'swa_rex_detail_attempted': 'Delivery attempted',
5✔
45
                'swa_rex_detail_creation_confirmed': 'Shipping label created',
5✔
46
                'swa_rex_detail_delivered': 'Package delivered',
5✔
47
                'swa_rex_detail_departed': 'Departed facility',
5✔
48
                'swa_rex_detail_exception': 'Exception occurred',
5✔
49
                'swa_rex_detail_held': 'Package held',
5✔
50
                'swa_rex_detail_in_transit': 'Package in transit',
5✔
51
                'swa_rex_detail_pickedUp': 'Package picked up',
5✔
52
                'swa_rex_detail_refused': 'Package refused',
5✔
53
                'swa_rex_detail_returned': 'Package returned',
5✔
54
                'swa_rex_detail_undeliverable': 'Package undeliverable',
5✔
55
                'swa_rex_intransit': 'Package in transit',
5✔
56
                'swa_rex_ofd': 'Out for delivery',
5✔
57
                'swa_rex_shipping_label_created': 'Shipping label created'
5✔
58
            };
5✔
59

5✔
60
            return summaryMap[statusSummary.localisedStringId] || statusSummary.localisedStringId;
5!
61
        }
5!
62

×
63
        return eventMap[eventCode] || eventCode;
5✔
64
    };
51✔
65

51✔
66
    this.isTrackingNumberValid = trackingNumber => {
51✔
67
        // Remove whitespace
28✔
68
        trackingNumber = trackingNumber.replace(/\s/g, '');
28✔
69
        trackingNumber = trackingNumber.toUpperCase();
28✔
70

28✔
71
        // Amazon Shipping tracking numbers: TB + (A|B|C) + 12 digits
28✔
72
        return /^TB[A-CM][0-9]{12}$/.test(trackingNumber);
28✔
73
    };
51✔
74

51✔
75
    this.track = async (trackingNumber, _options = {}) => {
51✔
76
        if (!_options.minDate) {
5✔
77
            _options.minDate = new Date(0);
5✔
78
        }
5✔
79

5✔
80
        // Clean tracking number
5✔
81
        trackingNumber = trackingNumber.replace(/\s/g, '').toUpperCase();
5✔
82

5✔
83
        const res = await fetch(`https://track.amazon.com/api/tracker/${trackingNumber}`, {
5✔
84
            signal: AbortSignal.timeout(30000)
5✔
85
        });
5✔
86

5✔
87
        if (!res.ok) {
5!
NEW
88
            throw await HttpError.from(res);
×
NEW
89
        }
×
90

5✔
91
        const json = await res.json();
5✔
92

5✔
93
        const results = {
5✔
94
            carrier: 'Amazon',
5✔
95
            events: [],
5✔
96
            raw: json,
5✔
97
            url: `https://track.amazon.com/tracking/${trackingNumber}`
5✔
98
        };
5✔
99

5✔
100
        if (!json) {
5!
NEW
101
            // No data returned, return empty results
×
NEW
102
            return results;
×
NEW
103
        }
×
104

5✔
105
        if (json.progressTracker) {
5✔
106
            const progressTracker = typeof json.progressTracker === 'string' ? JSON.parse(json.progressTracker) : json.progressTracker;
5!
107

5✔
108
            if (progressTracker.summary.metadata.expectedDeliveryDate) {
5✔
109
                let dateValue = progressTracker.summary.metadata.expectedDeliveryDate;
1✔
110
                if (typeof dateValue === 'object' && dateValue.date) {
1!
NEW
111
                    dateValue = dateValue.date;
×
UNCOV
112
                }
×
113
                const isoDate = new Date(dateValue);
1✔
114
                results.estimatedDeliveryDate = {
1✔
115
                    earliest: isoDate,
1✔
116
                    latest: isoDate
1✔
117
                };
1✔
118
            }
1✔
119
        }
5✔
120

5✔
121
        // Parse event history for detailed tracking events
5✔
122
        if (json.eventHistory) {
5✔
123
            const eventHistory = typeof json.eventHistory === 'string' ? JSON.parse(json.eventHistory) : json.eventHistory;
4!
124
            if (eventHistory.eventHistory && Array.isArray(eventHistory.eventHistory)) {
4✔
125
                for (let i = 0; i < eventHistory.eventHistory.length; i++) {
4✔
126
                    const event = eventHistory.eventHistory[i];
5✔
127

5✔
128
                    const trackingEvent = {
5✔
129
                        address: {},
5✔
130
                        date: new Date(event.eventTime),
5✔
131
                        description: parseEventDescription(event.eventCode, event.statusSummary),
5✔
132
                        details: event.eventCode
5✔
133
                    };
5✔
134

5✔
135
                    // Add location information if available
5✔
136
                    if (event.location) {
5✔
137
                        trackingEvent.address = {
2✔
138
                            city: event.location.city,
2✔
139
                            state: event.location.stateProvince,
2✔
140
                            country: event.location.countryCode,
2✔
141
                            zip: event.location.postalCode
2✔
142
                        };
2✔
143
                    }
2✔
144

5✔
145
                    // Set shipping date for events that indicate movement in carrier network
5✔
146
                    if (SHIPPED_EVENT_CODES.includes(event.eventCode) && !results.shippedAt) {
5✔
147
                        results.shippedAt = new Date(event.eventTime);
2✔
148
                    }
2✔
149

5✔
150
                    // Set delivery date for delivery events
5✔
151
                    if (DELIVERED_EVENT_CODES.includes(event.eventCode)) {
5✔
152
                        results.deliveredAt = new Date(event.eventTime);
1✔
153
                    }
1✔
154

5✔
155
                    // Filter events after minDate
5✔
156
                    if (trackingEvent.date >= _options.minDate) {
5✔
157
                        results.events.push(trackingEvent);
5✔
158
                    }
5✔
159
                }
5✔
160
            }
4✔
161
        }
4✔
162
        results.events.sort((a, b) => a.date - b.date);
5✔
163

5✔
164
        return results;
5✔
165
    };
51✔
166
}
51✔
167

12✔
168
module.exports = Amazon;
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc