fix: tweaks for test all to pass

Because:

* Test all didn't run in parallel to take advantage of more cores and
  a few older tests were flakey.
* Tests would hang as packages had a default test that was in watch
  mode.

This commit:

* Updates several flakey tests and runs the test all in parallel for a
  shorter completion time.
* Updates settings and payment-server packages to have new watch command
  and deafult test command that runs the tests.

Closes #FXA-6096
This commit is contained in:
Ben Bangert
2022-10-17 13:52:42 -07:00
parent 8a2bddea7d
commit ecb1a7f5ea
18 changed files with 400 additions and 416 deletions

View File

@@ -19,7 +19,8 @@ if [[ -z "$PACKAGE" ]]; then
>&2 echo "$help"
exit 1
elif [[ "$PACKAGE" == "all" ]]; then
yarn workspaces foreach --topological-dev run test
yarn stop && yarn start infrastructure && \
yarn workspaces foreach --topological-dev -v -p --exclude '*fxa-content-server*' --exclude '*functional-tests*' run test
else
echo "$workspaces run test" | xargs yarn workspaces foreach --topological-dev
fi

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -16,13 +16,15 @@ describe('audience tests', function () {
var idp = new IdP();
var client;
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.start(function (e1) {
client = new Client({ idp: idp });
done(e || e1);
});
});
before(async () => {
await new Promise((resolve) => idp.start(resolve));
await new Promise((resolve) => verifier.start(resolve));
client = new Client({ idp: idp });
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
var assertion;
@@ -97,12 +99,4 @@ describe('audience tests', function () {
done(err);
});
});
it('test servers should stop', function (done) {
idp.stop(function (e) {
verifier.stop(function (e1) {
done(e || e1);
});
});
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -15,45 +15,46 @@ describe('basic verifier test', function () {
var idp = new IdP();
var verifier = new Verifier();
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.setFallback(idp);
verifier.start(function (e1) {
done(e || e1);
});
});
before(async () => {
await new Promise((resolve) => idp.start(resolve));
await new Promise((resolve) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
it('should verify an assertion', function (done) {
var client = new Client({ idp: idp });
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
should.not.exist(err);
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
client.assertion(
{ audience: 'http://example.com' },
function (err, assertion) {
should.not.exist(err);
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
},
},
},
function (err, r) {
should.not.exist(err);
r.body.email.should.equal(client.email());
r.body.issuer.should.equal(idp.domain());
r.body.status.should.equal('okay');
r.body.audience.should.equal('http://example.com');
r.statusCode.should.equal(200);
shouldReturnSecurityHeaders(r);
done();
}
);
});
function (err, r) {
should.not.exist(err);
r.body.email.should.equal(client.email());
r.body.issuer.should.equal(idp.domain());
r.body.status.should.equal('okay');
r.body.audience.should.equal('http://example.com');
r.statusCode.should.equal(200);
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
it('should return 405 for GET requests', function (done) {
@@ -87,12 +88,4 @@ describe('basic verifier test', function () {
}
);
});
it('test servers should stop', function (done) {
idp.stop(function (e) {
verifier.stop(function (e1) {
done(e || e1);
});
});
});
});

View File

@@ -4,7 +4,7 @@
/* global describe,it */
require('should');
const should = require('should');
var Verifier = require('./lib/verifier.js'),
async = require('async'),
@@ -44,18 +44,17 @@ describe('cascading configuration files', function () {
);
});
it('test servers should start', function (done) {
it('test servers should start and finish cleanly', async () => {
verifier.buffer(true);
verifier.start(done);
should(verifier.process).equal(undefined);
await new Promise((resolve, error) => verifier.start(resolve));
should(verifier.process).not.equal(null);
await new Promise((resolve, error) => verifier.stop(resolve));
should(verifier.process).equal(null);
});
it('test servers should shutdown cleanly', function (done) {
verifier.stop(done);
});
it('verifier should have determined proper configuration', function (done) {
it('verifier should have determined proper configuration', () => {
verifier.buffer().indexOf('a.example.com').should.equal(-1);
verifier.buffer().indexOf('b.example.com').should.not.equal(-1);
done();
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -16,13 +16,15 @@ describe('content-type tests', function () {
var idp = new IdP();
var client;
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.start(function (e1) {
client = new Client({ idp: idp });
done(e || e1);
});
});
before(async () => {
await new Promise((resolve) => idp.start(resolve));
await new Promise((resolve) => verifier.start(resolve));
client = new Client({ idp: idp });
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
var assertion;
@@ -223,8 +225,4 @@ describe('content-type tests', function () {
}
);
});
it('test servers should stop', function (done) {
verifier.stop(done);
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -15,13 +15,16 @@ describe('fallback configuration test', function () {
var idp = new IdP();
var verifier = new Verifier();
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.setFallback(idp);
verifier.start(function (e1) {
done(e || e1);
});
});
before(async function () {
this.timeout(10000);
await new Promise((resolve) => idp.start(resolve));
verifier.setFallback(idp);
await new Promise((resolve) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
it('should verify an assertion vouched by the configured fallback', function (done) {
@@ -105,12 +108,4 @@ describe('fallback configuration test', function () {
}
);
});
it('test servers should stop', function (done) {
idp.stop(function (e) {
verifier.stop(function (e1) {
done(e || e1);
});
});
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -17,15 +17,17 @@ describe('force issuer', function () {
var client;
var verifier = new Verifier();
it('test idps should start up', function (done) {
idp.start(function (e) {
fallback.start(function (e1) {
verifier.setFallback(idp);
verifier.start(function (e2) {
done(e || e1 || e2);
});
});
});
before(async () => {
await new Promise((resolve, error) => idp.start(resolve));
await new Promise((resolve, error) => fallback.start(resolve));
verifier.setFallback(idp);
await new Promise((resolve, error) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve, error) => verifier.stop(resolve));
await new Promise((resolve, error) => fallback.stop(resolve));
await new Promise((resolve, error) => idp.stop(resolve));
});
it('assertion by fallback when primary support is present should fail', function (done) {
@@ -35,30 +37,30 @@ describe('force issuer', function () {
email: 'user@' + idp.domain(),
});
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
client.assertion(
{ audience: 'http://example.com' },
function (err, assertion) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('failure');
r.body.reason.should.startWith('untrusted issuer');
shouldReturnSecurityHeaders(r);
done();
}
);
});
function (_, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('failure');
r.body.reason.should.startWith('untrusted issuer');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
it('(v1) forceIssuer should over-ride authority discovery', function (done) {
@@ -68,30 +70,30 @@ describe('force issuer', function () {
email: 'user@' + idp.domain(),
});
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
client.assertion(
{ audience: 'http://example.com' },
function (_, assertion) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
shouldReturnSecurityHeaders(r);
done();
}
);
});
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
it('(v2) trustedIssuers should over-ride authority discovery', function (done) {
@@ -101,39 +103,29 @@ describe('force issuer', function () {
email: 'user@' + idp.domain(),
});
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
trustedIssuers: [fallback.domain()],
client.assertion(
{ audience: 'http://example.com' },
function (_, assertion) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
trustedIssuers: [fallback.domain()],
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
shouldReturnSecurityHeaders(r);
done();
}
);
});
});
it('test idp should shut down', function (done) {
idp.stop(function (e) {
fallback.stop(function (e1) {
verifier.stop(function (e2) {
done(e || e1 || e2);
});
});
});
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
require('should');
@@ -13,8 +13,12 @@ var Verifier = require('./lib/verifier.js'),
describe('health check', function () {
var verifier = new Verifier();
it('test server should start', function (done) {
verifier.start(done);
before(async () => {
await new Promise((resolve) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
});
it('health check should return OK', function (done) {
@@ -92,8 +96,4 @@ describe('health check', function () {
}
);
});
it('test server should stop', function (done) {
verifier.stop(done);
});
});

View File

@@ -89,6 +89,7 @@ Verifier.prototype.start = function (cb) {
cwd: repoBaseDir,
stdio: 'pipe',
env: e,
timeout: 4 * 1000,
}
);
@@ -123,7 +124,6 @@ Verifier.prototype.start = function (cb) {
var msg = 'exited';
if (code !== 0) {
msg += ' with code ' + code + ' (' + self.errBuf + ')';
console.error(msg);
}
if (cb) cb(msg);
cb = null;
@@ -136,10 +136,13 @@ Verifier.prototype.stop = function (cb) {
if (!this.process || !this._url) {
throw new Error('verifier not running');
}
this.process.kill('SIGINT');
this.process.on('exit', function (code) {
cb(!code ? null : 'non-zero exit code: ' + code);
});
const pid = this.process.pid;
// Really really kill it. This shouldn't be necesary, but sometimes when
// running tests in a loop, the process doesn't die with just a SIGINT.
cp.spawn('kill', ['-9', pid]);
};
module.exports = Verifier;

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var Verifier = require('./lib/verifier.js'),
should = require('should'),
@@ -12,8 +12,12 @@ var Verifier = require('./lib/verifier.js'),
describe('missing assertion test', function () {
var verifier = new Verifier();
it('test servers should start', function (done) {
verifier.start(done);
before(async () => {
await new Promise((resolve) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
});
it('should fail to verify when assertion is missing', function (done) {
@@ -36,8 +40,4 @@ describe('missing assertion test', function () {
}
);
});
it('test servers should stop', function (done) {
verifier.stop(done);
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -16,13 +16,15 @@ describe('audience tests', function () {
var idp = new IdP();
var client;
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.start(function (e1) {
client = new Client({ idp: idp });
done(e || e1);
});
});
before(async () => {
await new Promise((resolve) => idp.start(resolve));
await new Promise((resolve) => verifier.start(resolve));
client = new Client({ idp: idp });
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
var assertion;
@@ -75,12 +77,4 @@ describe('audience tests', function () {
}
);
});
it('test servers should stop', function (done) {
idp.stop(function (e) {
verifier.stop(function (e1) {
done(e || e1);
});
});
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -16,20 +16,22 @@ describe('audience tests', function () {
var idp = new IdP();
var client;
it('test servers should start', function (done) {
idp.start(function (e) {
verifier.start(function (e1) {
client = new Client({
idp: idp,
// note, using an email not rooted at the idp. trustIssuer is the only
// way this can work
email: 'user@example.com',
});
done(e || e1);
});
before(async () => {
await new Promise((resolve) => idp.start(resolve));
await new Promise((resolve) => verifier.start(resolve));
client = new Client({
idp: idp,
// note, using an email not rooted at the idp. trustIssuer is the only
// way this can work
email: 'user@example.com',
});
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => idp.stop(resolve));
});
var assertion;
it('test assertion should be created', function (done) {
@@ -84,23 +86,17 @@ describe('audience tests', function () {
});
it('should fail when trusted issuers contains non-strings', function (done) {
submitWithTrustedIssuers([idp.domain(), ['example.com']], function (
err,
r
) {
should.not.exist(err);
'failure'.should.equal(r.body.status);
'trusted issuers must be an array of strings'.should.equal(r.body.reason);
shouldReturnSecurityHeaders(r);
done();
});
});
it('test servers should stop', function (done) {
idp.stop(function (e) {
verifier.stop(function (e1) {
done(e || e1);
});
});
submitWithTrustedIssuers(
[idp.domain(), ['example.com']],
function (err, r) {
should.not.exist(err);
'failure'.should.equal(r.body.status);
'trusted issuers must be an array of strings'.should.equal(
r.body.reason
);
shouldReturnSecurityHeaders(r);
done();
}
);
});
});

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global describe,it */
/* global describe,it,before,after */
var IdP = require('browserid-local-verify/testing').IdP,
Client = require('browserid-local-verify/testing').Client,
@@ -16,13 +16,15 @@ describe('unverified email', function () {
var verifier = new Verifier();
var client;
it('test idps should start up', function (done) {
fallback.start(function (e1) {
verifier.setFallback(fallback);
verifier.start(function (e2) {
done(e1 || e2);
});
});
before(async () => {
await new Promise((resolve) => fallback.start(resolve));
verifier.setFallback(fallback);
await new Promise((resolve) => verifier.start(resolve));
});
after(async () => {
await new Promise((resolve) => verifier.stop(resolve));
await new Promise((resolve) => fallback.stop(resolve));
});
it('(v1) assertion with unverified email address should fail to verify', function (done) {
@@ -32,30 +34,30 @@ describe('unverified email', function () {
});
// clear email
client.email(null);
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
client.assertion(
{ audience: 'http://example.com' },
function (_, assertion) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('failure');
r.body.reason.should.startWith('untrusted assertion');
shouldReturnSecurityHeaders(r);
done();
}
);
});
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('failure');
r.body.reason.should.startWith('untrusted assertion');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
it('(v1) assertion with unverified email address and forceIssuer should verify', function (done) {
@@ -63,33 +65,35 @@ describe('unverified email', function () {
idp: fallback,
principal: { 'unverified-email': 'bob@example.com' },
});
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
client.assertion(
{ audience: 'http://example.com' },
function (_, assertion) {
request(
{
method: 'post',
url: verifier.url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
r.body.idpClaims.should.be.type('object');
r.body.idpClaims['unverified-email'].should.equal('bob@example.com');
r.body.should.not.have.property('unverified-email');
shouldReturnSecurityHeaders(r);
done();
}
);
});
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
r.body.idpClaims.should.be.type('object');
r.body.idpClaims['unverified-email'].should.equal(
'bob@example.com'
);
r.body.should.not.have.property('unverified-email');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
it('(v1) allowUnverified causes extraction of unverified email addresses', function (done) {
@@ -98,41 +102,35 @@ describe('unverified email', function () {
principal: { 'unverified-email': 'bob@example.com' },
});
client.assertion({ audience: 'http://example.com' }, function (
err,
assertion
) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
experimental_allowUnverified: true,
client.assertion(
{ audience: 'http://example.com' },
function (_, assertion) {
request(
{
method: 'post',
url: verifier.v1url(),
json: true,
body: {
assertion: assertion,
audience: 'http://example.com',
experimental_forceIssuer: fallback.domain(),
experimental_allowUnverified: true,
},
},
},
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
r.body.idpClaims.should.be.type('object');
r.body.idpClaims['unverified-email'].should.equal('bob@example.com');
r.body.should.have.property('unverified-email');
shouldReturnSecurityHeaders(r);
done();
}
);
});
});
it('test idp should shut down', function (done) {
fallback.stop(function (e1) {
verifier.stop(function (e2) {
done(e1 || e2);
});
});
function (err, r) {
should.not.exist(err);
r.statusCode.should.equal(200);
r.body.status.should.equal('okay');
r.body.idpClaims.should.be.type('object');
r.body.idpClaims['unverified-email'].should.equal(
'bob@example.com'
);
r.body.should.have.property('unverified-email');
shouldReturnSecurityHeaders(r);
done();
}
);
}
);
});
});

View File

@@ -102,9 +102,24 @@ describe('PaymentConfigManager', () => {
Container.set(AuthFirestore, firestore);
Container.set(AuthLogger, {});
Container.set(AppConfig, mockConfig);
paymentConfigManager = new PaymentConfigManager();
productConfigDbRef = paymentConfigManager.productConfigDbRef;
planConfigDbRef = paymentConfigManager.planConfigDbRef;
// Ensure the collections are clean in case anything else might
// not have cleaned up properly. This helps reduce flaky tests.
await deleteCollection(
paymentConfigManager.firestore,
productConfigDbRef,
100
);
await deleteCollection(
paymentConfigManager.firestore,
planConfigDbRef,
100
);
await productConfigDbRef.doc(testProductId).set(productConfig);
testPlanConfig = {
...planConfig,
@@ -113,6 +128,20 @@ describe('PaymentConfigManager', () => {
productConfigId: testProductId,
};
await planConfigDbRef.doc(testPlanId).set(testPlanConfig);
// Ensure all the plans/products have loaded. Some delays may occur
// due to triggering of the firestore listeners.
await retry(
async () => {
await paymentConfigManager.maybeLoad();
assert.lengthOf(await paymentConfigManager.allProducts(), 1);
assert.lengthOf(await paymentConfigManager.allPlans(), 1);
},
{
retries: 50,
minTimeout: 10,
}
);
mergedConfig = mergeConfigs(testPlanConfig, productConfig);
});

View File

@@ -7,93 +7,85 @@
const { assert } = require('chai');
const TestServer = require('../test_server');
const Client = require('../client')();
const retry = require('async-retry');
const config = require('../../config').getProperties();
config.redis.sessionTokens.enabled = false;
const key = {
algorithm: 'RS',
n:
'4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
n: '4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
e: '65537',
};
describe('remote account locale', function () {
this.timeout(15000);
let server;
before(() => {
return TestServer.start(config).then((s) => {
server = s;
});
before(async () => {
server = await TestServer.start(config);
});
it('signing a cert against an account with no locale will save the locale', () => {
after(async () => {
await TestServer.stop(server);
});
it('signing a cert against an account with no locale will save the locale', async () => {
const email = server.uniqueEmail();
const password = 'ilikepancakes';
let client;
return Client.createAndVerify(
const client = await Client.createAndVerify(
config.publicUrl,
email,
password,
server.mailbox
)
.then((c) => {
client = c;
return c.api.accountStatus(c.uid, c.sessionToken);
})
.then((response) => {
assert.ok(!response.locale, 'account has no locale');
return client.login();
})
.then(() => {
return client.api.certificateSign(
client.sessionToken,
key,
1000,
'en-US'
);
let response = await client.api.accountStatus(
client.uid,
client.sessionToken
);
assert.ok(!response.locale, 'account has no locale');
await client.login();
// Certificate sign kicks off async updates that are not waited on, therefore
// we must retry the accouunt status check until the locale is updated.
await client.api.certificateSign(client.sessionToken, key, 1000, 'en-US');
await retry(
async () => {
response = await client.api.accountStatus(
client.uid,
client.sessionToken
);
})
.then(() => {
return client.api.accountStatus(client.uid, client.sessionToken);
})
.then((response) => {
assert.equal(response.locale, 'en-US', 'account has a locale');
});
},
{
retries: 10,
minTimeout: 20,
}
);
});
it('a really long (invalid) locale', () => {
it('a really long (invalid) locale', async () => {
const email = server.uniqueEmail();
const password = 'ilikepancakes';
return Client.create(config.publicUrl, email, password, {
const client = await Client.create(config.publicUrl, email, password, {
lang: Buffer.alloc(128).toString('hex'),
})
.then((c) => {
return c.api.accountStatus(c.uid, c.sessionToken);
})
.then((response) => {
assert.ok(!response.locale, 'account has no locale');
});
});
const response = await client.api.accountStatus(
client.uid,
client.sessionToken
);
assert.ok(!response.locale, 'account has no locale');
});
it('a really long (valid) locale', () => {
it('a really long (valid) locale', async () => {
const email = server.uniqueEmail();
const password = 'ilikepancakes';
return Client.create(config.publicUrl, email, password, {
const client = await Client.create(config.publicUrl, email, password, {
lang: `en-US,en;q=0.8,${Buffer.alloc(128).toString('hex')}`,
})
.then((c) => {
return c.api.accountStatus(c.uid, c.sessionToken);
})
.then((response) => {
assert.equal(
response.locale,
'en-US,en;q=0.8',
'account has no locale'
);
});
});
after(() => {
return TestServer.stop(server);
});
const response = await client.api.accountStatus(
client.uid,
client.sessionToken
);
assert.equal(response.locale, 'en-US,en;q=0.8', 'account has no locale');
});
});

View File

@@ -24,9 +24,9 @@ describe('send-email-batches', () => {
let totalTimeMS;
const DELAY_BETWEEN_BATCHES_MS = 100;
const DELAY_BETWEEN_BATCHES_MS = 120;
before(() => {
before(async () => {
sendEmailBatchSpy = sinon.spy((batch) => {
if (batch.indexOf('c') > -1) {
return Promise.resolve({
@@ -49,15 +49,14 @@ describe('send-email-batches', () => {
);
const startTime = Date.now();
return sendEmailBatches(
await sendEmailBatches(
batches,
DELAY_BETWEEN_BATCHES_MS,
sender,
log,
false
).then(() => {
totalTimeMS = Date.now() - startTime;
});
);
totalTimeMS = Date.now() - startTime;
});
it('calls log as expected', () => {
@@ -82,16 +81,15 @@ describe('send-email-batches', () => {
assert.strictEqual(sendEmailBatchSpy.args[1][1], sender);
});
it(
'uses a delay between batches',
async () => {
await retry(async () => {
assert.isAbove(totalTimeMS, 100);
});
},
{
retries: 10,
minTimeout: 20,
}
);
it('uses a delay between batches', async () => {
await retry(
async () => {
assert.isAbove(totalTimeMS, 80);
},
{
retries: 10,
minTimeout: 20,
}
);
}).timeout(15000);
});

View File

@@ -15,7 +15,8 @@
"build": "tsc --build ../fxa-react && NODE_ENV=production npm run build-css && SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/ INLINE_RUNTIME_CHUNK=false CI=false rescripts build",
"eject": "react-scripts eject",
"test": "npm-run-all test:frontend test:server",
"test:frontend": "SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/ INLINE_RUNTIME_CHUNK=false rescripts test",
"test:frontend": "SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/ INLINE_RUNTIME_CHUNK=false rescripts test --watchAll=false",
"test:frontend:watch": "SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/ INLINE_RUNTIME_CHUNK=false rescripts test",
"test:server": "jest --runInBand --coverage --verbose --config server/jest.config.js --forceExit",
"format": "prettier --write --config ../../_dev/.prettierrc '**'",
"storybook": "start-storybook -p 6006",

View File

@@ -16,7 +16,8 @@
"stop": "pm2 stop pm2.config.js",
"delete": "pm2 delete pm2.config.js",
"storybook": "STORYBOOK_BUILD=1 npm run build-css && start-storybook -p 6008 --no-version-updates",
"test": "SKIP_PREFLIGHT_CHECK=true rescripts test",
"test": "SKIP_PREFLIGHT_CHECK=true rescripts test --watchAll=false",
"test:watch": "SKIP_PREFLIGHT_CHECK=true rescripts test",
"test:coverage": "yarn test --coverage --watchAll=false"
},
"jest": {