diff --git a/.nvmrc b/.nvmrc index 43708bb6b4..9075659573 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1,2 +1 @@ -10.14.2 - +20.15.0 diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 9f10cf781e..4284c7365b 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -141,35 +141,6 @@ describe('Auth', () => { expect(userAuth.user.id).toBe(user.id); }); - it('should load auth without a config', async () => { - const user = new Parse.User(); - await user.signUp({ - username: 'hello', - password: 'password', - }); - expect(user.getSessionToken()).not.toBeUndefined(); - const userAuth = await getAuthForSessionToken({ - sessionToken: user.getSessionToken(), - }); - expect(userAuth.user instanceof Parse.User).toBe(true); - expect(userAuth.user.id).toBe(user.id); - }); - - it('should load auth with a config', async () => { - const user = new Parse.User(); - await user.signUp({ - username: 'hello', - password: 'password', - }); - expect(user.getSessionToken()).not.toBeUndefined(); - const userAuth = await getAuthForSessionToken({ - sessionToken: user.getSessionToken(), - config: Config.get('test'), - }); - expect(userAuth.user instanceof Parse.User).toBe(true); - expect(userAuth.user.id).toBe(user.id); - }); - describe('getRolesForUser', () => { const rolesNumber = 100; diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index ee232887c9..e428c81254 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -469,29 +469,6 @@ describe('AuthenticationProviders', function () { expect(providerOptions).toEqual(options.facebook); }); - it('should throw error when Facebook request appId is wrong data type', async () => { - const httpsRequest = require('../lib/Adapters/Auth/httpsRequest'); - spyOn(httpsRequest, 'get').and.callFake(() => { - return Promise.resolve({ id: 'a' }); - }); - const options = { - facebook: { - appIds: 'abcd', - appSecret: 'secret_sauce', - }, - }; - const authData = { - access_token: 'badtoken', - }; - const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter( - 'facebook', - options - ); - await expectAsync(adapter.validateAppId(appIds, authData, providerOptions)).toBeRejectedWith( - new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'appIds must be an array.') - ); - }); - it('should handle Facebook appSecret for validating appIds', async () => { const httpsRequest = require('../lib/Adapters/Auth/httpsRequest'); spyOn(httpsRequest, 'get').and.callFake(() => { @@ -1652,7 +1629,7 @@ describe('apple signin auth adapter', () => { } }); - it('(using client id as string) should throw error with with invalid jwt issuer', async () => { + it('(using client id as string) should throw error with with invalid jwt issuer with token', async () => { const fakeClaim = { iss: 'https://not.apple.com', sub: 'the_user_id', @@ -2208,7 +2185,7 @@ describe('facebook limited auth adapter', () => { } }); - it('(using client id as string) should throw error with with invalid jwt issuer', async () => { + it('(using client id as string) with token', async () => { const fakeClaim = { iss: 'https://not.facebook.com', sub: 'the_user_id', diff --git a/spec/AuthenticationAdaptersV2.spec.js b/spec/AuthenticationAdaptersV2.spec.js index e9486187ef..d5aa8a5898 100644 --- a/spec/AuthenticationAdaptersV2.spec.js +++ b/spec/AuthenticationAdaptersV2.spec.js @@ -369,16 +369,6 @@ describe('Auth Adapter features', () => { expect(spy).toHaveBeenCalled(); }); - it('should throw if no triggers found', async () => { - await reconfigureServer({ auth: { wrongAdapter } }); - const user = new Parse.User(); - await expectAsync( - user.save({ authData: { wrongAdapter: { id: 'wrongAdapter' } } }) - ).toBeRejectedWithError( - 'Adapter is not configured. Implement either validateAuthData or all of the following: validateSetUp, validateLogin and validateUpdate' - ); - }); - it('should throw if policy does not match one of default/solo/additional', async () => { const adapterWithBadPolicy = { validateAppId: () => Promise.resolve(), diff --git a/spec/CloudCode.Validator.spec.js b/spec/CloudCode.Validator.spec.js index 196568f763..f9e7a44c82 100644 --- a/spec/CloudCode.Validator.spec.js +++ b/spec/CloudCode.Validator.spec.js @@ -194,27 +194,6 @@ describe('cloud validator', () => { }); }); - it('set params on cloud functions', done => { - Parse.Cloud.define( - 'hello', - () => { - return 'Hello world!'; - }, - { - fields: ['a'], - } - ); - Parse.Cloud.run('hello', {}) - .then(() => { - fail('function should have failed.'); - }) - .catch(error => { - expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR); - expect(error.message).toEqual('Validation failed. Please specify data for a.'); - done(); - }); - }); - it('allow params on cloud functions', done => { Parse.Cloud.define( 'hello', @@ -1629,7 +1608,7 @@ describe('cloud validator', () => { } }); - it('Logs on invalid config', () => { + it('Logs on multiple invalid configs', () => { const fields = [ { field: 'otherKey', diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index fcfeba416b..6480771956 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -49,6 +49,7 @@ describe('Cloud Code', () => { }); it('cloud code must be valid type', async () => { + spyOn(console, 'error').and.callFake(() => {}); await expectAsync(reconfigureServer({ cloud: true })).toBeRejectedWith( "argument 'cloud' must either be a string or a function" ); diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index c7c58f8ad5..1624007e0d 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -789,59 +789,11 @@ describe('Parse.File testing', () => { headers: { 'Content-Type': 'application/octet-stream', 'X-Parse-Application-Id': 'test', - Range: 'bytes=abc-efs', }, }).catch(e => e); expect(file.headers['content-range']).toBeUndefined(); }); - it('supports bytes range if start and end undefined', async () => { - const headers = { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }; - const response = await request({ - method: 'POST', - headers: headers, - url: 'http://localhost:8378/1//files/file.txt ', - body: repeat('argle bargle', 100), - }); - const b = response.data; - const file = await request({ - url: b.url, - headers: { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - }, - }).catch(e => e); - expect(file.headers['content-range']).toBeUndefined(); - }); - - it('supports bytes range if end is greater than size', async () => { - const headers = { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }; - const response = await request({ - method: 'POST', - headers: headers, - url: 'http://localhost:8378/1//files/file.txt ', - body: repeat('argle bargle', 100), - }); - const b = response.data; - const file = await request({ - url: b.url, - headers: { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - Range: 'bytes=0-2000', - }, - }).catch(e => e); - expect(file.headers['content-range']).toBe('bytes 0-1212/1212'); - }); - it('supports bytes range if end is greater than size', async () => { const headers = { 'Content-Type': 'application/octet-stream', diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js index 22e0918d1b..ef6e017065 100644 --- a/spec/ParseLiveQuery.spec.js +++ b/spec/ParseLiveQuery.spec.js @@ -382,7 +382,6 @@ describe('ParseLiveQuery', function () { await obj2.save(); obj2.set('foo', 'bart'); await obj2.save(); - await sleep(2000); expect(createSpy).toHaveBeenCalledTimes(1); expect(updateSpy).toHaveBeenCalledTimes(1); }); diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index 04fb3fff58..9961b2503d 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -1633,35 +1633,6 @@ describe('ParseLiveQueryServer', function () { }); }); - it('matches CLP when find is restricted to userIds', done => { - const parseLiveQueryServer = new ParseLiveQueryServer({}); - const acl = new Parse.ACL(); - acl.setReadAccess(testUserId, true); - // Mock sessionTokenCache will return false when sessionToken is undefined - const client = { - sessionToken: 'sessionToken', - getSubscriptionInfo: jasmine.createSpy('getSubscriptionInfo').and.returnValue({ - sessionToken: 'userId', - }), - }; - const requestId = 0; - - parseLiveQueryServer - ._matchesCLP( - { - find: { userId: true }, - }, - { className: 'Yolo' }, - client, - requestId, - 'find' - ) - .then(isMatched => { - expect(isMatched).toBe(true); - done(); - }); - }); - it('matches CLP when find is restricted to userIds', done => { const parseLiveQueryServer = new ParseLiveQueryServer({}); const acl = new Parse.ACL(); diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index a43ceb6662..aa5e692fe4 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -362,7 +362,7 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => { await dropTable(client, tableName); }); - it('should use index for caseInsensitive query', async () => { + it('should use index for caseInsensitive query with user', async () => { await adapter.deleteAllClasses(); const config = Config.get('test'); config.schemaCache.clear(); diff --git a/spec/PushWorker.spec.js b/spec/PushWorker.spec.js index 63e0945110..5e57eb8827 100644 --- a/spec/PushWorker.spec.js +++ b/spec/PushWorker.spec.js @@ -120,7 +120,7 @@ describe('PushWorker', () => { }); }); - it('transforms body appropriately', () => { + it('transforms body appropriately with title locale', () => { const cleanBody = PushUtils.transformPushBodyForLocale( { data: { diff --git a/spec/helper.js b/spec/helper.js index 1c73c447ad..afc7e9d112 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -286,6 +286,10 @@ afterEach(function (done) { .then(afterLogOut); }); +afterAll(() => { + global.displaySlowTests(); +}); + const TestObject = Parse.Object.extend({ className: 'TestObject', }); diff --git a/spec/support/CurrentSpecReporter.js b/spec/support/CurrentSpecReporter.js index 3158e21eae..1e7f94362d 100755 --- a/spec/support/CurrentSpecReporter.js +++ b/spec/support/CurrentSpecReporter.js @@ -1,15 +1,45 @@ // Sets a global variable to the current test spec // ex: global.currentSpec.description - +const { performance } = require('perf_hooks'); global.currentSpec = null; +const timerMap = {}; +const duplicates = []; +/** The minimum execution time in seconds for a test to be considered slow. */ +const slowTestLimit = 2; + class CurrentSpecReporter { specStarted(spec) { + if (timerMap[spec.fullName]) { + console.log('Duplicate spec: ' + spec.fullName); + duplicates.push(spec.fullName); + } + timerMap[spec.fullName] = performance.now(); global.currentSpec = spec; } - specDone() { + specDone(result) { + if (result.status === 'excluded') { + delete timerMap[result.fullName]; + return; + } + timerMap[result.fullName] = (performance.now() - timerMap[result.fullName]) / 1000; global.currentSpec = null; } } +global.displaySlowTests = function() { + const times = Object.values(timerMap).sort((a,b) => b - a); + if (times.length > 0) { + console.log(`Slow tests with execution time >=${slowTestLimit}s:`); + } + times.forEach((time) => { + if (time >= slowTestLimit) { + console.warn(`${time.toFixed(1)}s:`, Object.keys(timerMap).find(key => timerMap[key] === time)); + } + }); + console.log('\n'); + duplicates.forEach((spec) => { + console.warn('Duplicate spec: ' + spec); + }); +}; module.exports = CurrentSpecReporter;