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

mozilla / blurts-server / #13258

pending completion
#13258

push

circleci

Vinnl
Update filter results when clearing search field

On the public breach list, the search input that filters the list
of breaches would respond to `keyup` events specifically, rather
than anything that might change the input. Thus, if (e.g. in Chrome
or Safari) a browser adds a "Clear input" icon to the field and the
user clicks that, the field gets emptied, but the list of breaches
are still narrowed down to the previous input.

282 of 1663 branches covered (16.96%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

959 of 4511 relevant lines covered (21.26%)

1.77 hits per line

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

0.0
/controllers/email-l10n.js
1
'use strict'
2

3
const EmailUtils = require('../email-utils')
×
4
const AppConstants = require('../app-constants')
×
5
const path = require('path')
×
6
const { readFile } = require('fs/promises')
×
7

8
const partials = ['alert', 'report', 'email_verify', 'email-monthly-unresolved']
×
9
const mockBreaches = ['Dropbox', 'Apollo', 'Adobe']
×
10
const mockBreachStats = {
×
11
  passwords: {
12
    count: 1,
13
    numResolved: 0
14
  },
15
  numBreaches: {
16
    count: 2,
17
    numResolved: 0,
18
    numUnresolved: 2
19
  },
20
  monitoredEmails: {
21
    count: 2
22
  }
23
}
24

25
async function getEmailMockup (req, res) {
26
  if (!['dev', 'heroku', 'stage'].includes(AppConstants.NODE_ENV)) return res.sendStatus(404)
×
27

28
  if (!req.query.partial) {
×
29
    return res.redirect('/email-l10n/?partial=email_verify&type=email_verify') // default when no specific partial requested
×
30
  } else if (!partials.includes(req.query.partial)) {
×
31
    return res.sendStatus(404) // requested partial is not in partials list
×
32
  }
33

34
  const emailStr = await readFile(path.resolve('views/layouts/email-2022.hbs'), { encoding: 'utf-8' })
×
35
  const emailStyle = emailStr.substring(emailStr.indexOf('<style>'), emailStr.indexOf('</style>') + 8)
×
36
  const { unsafeBreachesForEmail, emailSubject, breachAlert, unsubscribeUrl, heading, subheading } = getPartialData(req.query.type, req.app.locals.breaches)
×
37
  const utmCampaign = req.query.type
×
38

39
  res.render('email_l10n', {
×
40
    layout: 'email_l10n_mockups.hbs',
41
    unsafeBreachesForEmail,
42
    supportedLocales: req.supportedLocales,
43
    whichPartial: `email_partials/${req.query.partial}`,
44
    partialType: req.query.type,
45
    breachedEmail: req.user?.primary_email || 'breachedEmail@testing.com',
×
46
    breachAlert,
47
    emailSubject: req.fluentFormat(emailSubject),
48
    heading: req.fluentFormat(heading),
49
    subheading: req.fluentFormat(subheading),
50
    ctaHref: EmailUtils.getEmailCtaHref(utmCampaign, 'dashboard-cta'),
51
    utmCampaign,
52
    emailStyle,
53
    unsubscribeUrl,
54
    csrfToken: req.csrfToken(),
55
    breachStats: mockBreachStats
56
  })
57
}
58

59
function getPartialData (partialType, breaches) {
60
  const unsafeBreachesForEmail = []
×
61
  let emailSubject, breachAlert, unsubscribeUrl, heading, subheading
62

63
  switch (partialType) {
×
64
    case 'email_verify':
65
      emailSubject = 'email-subject-verify'
×
66
      heading = 'email-verify-heading'
×
67
      subheading = 'email-verify-subhead'
×
68
      break
×
69
    case 'noBreaches':
70
      emailSubject = 'email-subject-no-breaches'
×
71
      heading = 'email-breach-summary'
×
72
      break
×
73
    case 'singleBreach':
74
      emailSubject = 'email-subject-found-breaches'
×
75
      heading = 'email-breach-summary'
×
76
      unsafeBreachesForEmail.push(breaches.find(breach => breach.Name === mockBreaches[0]))
×
77
      break
×
78
    case 'multipleBreaches':
79
      emailSubject = 'email-subject-found-breaches'
×
80
      heading = 'email-breach-summary'
×
81
      mockBreaches.forEach(name => {
×
82
        unsafeBreachesForEmail.push(breaches.find(breach => breach.Name === name))
×
83
      })
84
      break
×
85
    case 'alert':
86
      emailSubject = 'breach-alert-subject'
×
87
      heading = 'email-spotted-new-breach'
×
88
      breachAlert = breaches.find(breach => breach.Name === 'LinkedIn')
×
89
      break
×
90
    case 'email-monthly-unresolved':
91
      emailSubject = 'email-unresolved-heading'
×
92
      heading = 'email-unresolved-heading'
×
93
      subheading = 'email-unresolved-subhead'
×
94
      unsubscribeUrl = 'fakeunsubscribe.test.com'
×
95
      break
×
96
  }
97

98
  return { unsafeBreachesForEmail, emailSubject, breachAlert, unsubscribeUrl, heading, subheading }
×
99
}
100

101
async function sendTestEmail (req, res) {
102
  const { unsafeBreachesForEmail, emailSubject, breachAlert, heading, subheading } = getPartialData(req.body.partialType, req.app.locals.breaches)
×
103
  const supportedLocales = req.supportedLocales
×
104

105
  const unsubscribeUrl = EmailUtils.getMonthlyUnsubscribeUrl(req.user, 'monthly-unresolved', 'unsubscribe-cta')
×
106
  const utmCampaign = req.body.partialType
×
107
  const context = {
×
108
    whichPartial: req.body.whichPartial,
109
    supportedLocales,
110
    heading: req.fluentFormat(heading),
111
    subheading: req.fluentFormat(subheading),
112
    breachedEmail: req.user.primary_email,
113
    unsafeBreachesForEmail,
114
    breachAlert,
115
    breachStats: req.user.breach_stats,
116
    unsubscribeUrl,
117
    ctaHref: EmailUtils.getEmailCtaHref(utmCampaign, 'dashboard-cta'),
118
    utmCampaign
119
  }
120

121
  await EmailUtils.sendEmail(req.body.recipientEmail, req.fluentFormat(emailSubject), 'email-2022', context)
×
122

123
  res.send(`
×
124
    <h2>Email sent!</h2>
125
    <a href='/email-l10n/'>Go Back</a> | <a href='/user/logout'>Sign Out</a>
126
    `)
127
}
128

129
function notFound (req, res) {
130
  res.status(404)
×
131
  res.render('subpage', {
×
132
    analyticsID: 'error',
133
    headline: req.fluentFormat('error-headline'),
134
    subhead: req.fluentFormat('home-not-found')
135
  })
136
}
137

138
module.exports = {
×
139
  getEmailMockup,
140
  notFound,
141
  sendTestEmail
142
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc