Best JavaScript code snippet using playwright-internal
update.js
Source:update.js
1'use strict';2var events = require('events');3var env = require('./env');4var gUrl = require('url');5var http = require('http');6var https = require('https');7var path = require('path');8var fs = require('fs');9var evtType = require('./EventVariable').EventTypes;10var funcVar = require('./FunctionVariable');11var cp = require('child_process');12var os = require('os');13var request = require('request');14var AppData = require('./AppData');15var __extends = this.__extends || function (d, b) {16 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];17 function __() { this.constructor = d; }18 __.prototype = b.prototype;19 d.prototype = new __();20};21var UpdateClass = (function (_super) {22 __extends(UpdateClass, _super);23 var _this;24 function UpdateClass() {25 _this = this; 26 _super.call(this); 27 env.log('UpdateClass','UpdateClass','Begin...');28 try29 {30 }catch(e){31 throw new Error(e);32 } 33 _this.AppFileDownload = false;34 }35 var GetEventParamerObj = function (sn, func, param){36 var Obj = {37 Type : funcVar.FuncType.System,38 SN : sn,39 Func : func,40 Param : param41 };42 return Obj;43 };44 var GetExtFilePath = function (aPath, ext){45 var files = [];46 if(fs.existsSync(aPath)) {47 files = fs.readdirSync(aPath);48 for (var file of files){49 if (file.endsWith(ext)){50 var curPath = path.join(aPath, file);51 return curPath;52 }53 }54 }55 }; 56 UpdateClass.prototype.UpdateApp = function () {57 env.log('UpdateClass','UpdateClass','UpdateApp');58 return new Promise(function(resolve,reject){59 try{60 if(env.isMac && fs.existsSync(os.tmpdir()+"/GSPYUpdate"))61 {62 var Obj={63 Type : funcVar.FuncType.System,64 Func : evtType.UpdateApp,65 Param : 066 };67 _this.emit(evtType.ProtocolMessage, Obj);68 return resolve();69 }70 else if(env.isWindows && fs.existsSync(os.tmpdir()+"\\"+"GSPYUpdate")){71 var Obj={72 Type : funcVar.FuncType.System,73 SN : null,74 Func : evtType.UpdateApp,75 Param : 076 };77 _this.emit(evtType.ProtocolMessage, Obj);78 return resolve();79 }80 request.get(AppData.AppSettingData.UpdateUrl+'/UpdateApp.json',function(err, resp, body){81 var body = JSON.parse(body);82 if(body.hasOwnProperty('Version') && env.CompareVersion(AppData.AppSettingData.Version,body.Version)){83 var fromFile;84 var toFile; 85 if(env.isWindows){86 fromFile = AppData.AppSettingData.UpdateUrl+body.AppName.Win;87 toFile = os.tmpdir()+"\\"+AppData.AppSettingData.ProjectName+".zip";88 }89 else{90 fromFile = AppData.AppSettingData.UpdateUrl+body.AppName.Mac;91 toFile = os.tmpdir()+"/"+AppData.AppSettingData.ProjectName+".zip";92 }93 _this.DownloadFileFromURL(fromFile, toFile, true).then(function(obj){94 // _this.DownloadInstallPackage(function(){95 env.log('UpdateClass','UpdateApp','DownloadFileFromURL success');96 var Obj={97 Type : funcVar.FuncType.System,98 SN : null,99 Func : evtType.UpdateApp,100 Param : 0101 };102 103 _this.emit(evtType.ProtocolMessage, Obj);104 105 resolve();106 // })107 })108 }else{109 resolve();110 }111 })112 }catch(ex){113 reject(ex);114 }115 });116 }117 UpdateClass.prototype.DownloadFileFromURL = function (url, dest, emitProgress) { 118 return new Promise(function (resolve, reject) {119 try{ 120 env.log('UpdateClass','DownloadFileFromURL',`Begin downloadFile:${url} ${dest}`); 121 var isError = false;122 var preStep = 0, curStep = 0;123 var urlObj = gUrl.parse(url);124 var protocol = urlObj.protocol == 'https:' ? https : http;125 var opts;126 var req = null;127 if (_this.ProxyEnable){128 opts = {129 host: _this.ProxyHost,130 port: _this.ProxyPort,131 path: url,132 // timeout:5000,133 headers: {134 Host: urlObj.host135 }136 };137 }else{138 opts = url;139 }140 var file = fs.createWriteStream(dest);141 req = protocol.get(opts, function(response) {142 var totalLen = parseInt(response.headers['content-length'], 10);143 var cur = 0; 144 file.on('finish', function() {145 file.close(function(error, data){146 if (!isError){147 resolve({Data : dest});148 }149 });150 });151 if(emitProgress){152 response.on("data", function(chunk) {153 cur += chunk.length;154 curStep = Math.floor(cur / totalLen *100);155 if (preStep !== curStep){156 preStep = curStep;157 var Obj = GetEventParamerObj(null, evtType.DownloadProgress, {Current : cur,Total : totalLen});158 _this.emit(evtType.ProtocolMessage, Obj);159 }160 if(_this.DownloadFileCancel) {161 env.log('UpdateClass','DownloadFileFromURL',`User Cancel DownloadFile`); 162 req.abort();163 _this.DownloadFileCancel = false;164 } 165 if(_this.CheckDownloadTimeoutId != null)166 {167 clearTimeout( _this.CheckDownloadTimeoutId );168 _this.CheckDownloadTimeoutId = null;169 }170 _this.CheckDownloadTimeoutId = setTimeout(function(){171 env.log('UpdateClass','DownloadFileFromURL',`server is not responsed`);172 173 file.close(function(error, data){174 fs.unlink(dest, function(){175 var obj = {176 Error : 0x1008,177 Data : null178 };179 resolve(obj);180 req.abort();181 _this.DownloadFileCancel = false;182 }); 183 });184 }, 15000);185 });186 response.on("end", function(chunk) {187 env.log('UpdateClass','DownloadFileFromURL',`get data end`);188 // var Obj={189 // Type : funcVar.FuncType.System,190 // SN : null,191 // Func : evtType.UpdateApp,192 // Param : 0193 // };194 // _this.emit(evtType.ProtocolMessage, Obj);195 196 if(_this.CheckDownloadTimeoutId != null)197 {198 clearTimeout( _this.CheckDownloadTimeoutId );199 _this.CheckDownloadTimeoutId = null;200 }201 });202 }203 response.pipe(file);204 }).on('error', function(err) {205 isError = true; _this.DownloadFileCancel = false;206 env.log('Error','DownloadFileFromURL',`[downloadFile error:${err} url:${url}]`); 207 file.close(function(error, data){208 fs.unlink(dest, function(){209 var obj = {210 Error : 0x1008,211 Data : err212 };213 resolve(obj);214 }); 215 });216 var Obj = GetEventParamerObj(null, evtType.DownloadFileError, null);217 _this.emit(evtType.ProtocolMessage, Obj); 218 if(_this.CheckDownloadTimeoutId != null)219 {220 clearTimeout( _this.CheckDownloadTimeoutId );221 _this.CheckDownloadTimeoutId = null;222 }223 });224 }catch(ex){ 225 env.log('Error','DownloadFileFromURL',`ex:${ex.message}`); 226 var obj = {227 Error : 0x1008,228 Data : err229 };230 if(_this.CheckDownloadTimeoutId != null)231 {232 clearTimeout( _this.CheckDownloadTimeoutId );233 _this.CheckDownloadTimeoutId = null;234 }235 var Obj = GetEventParamerObj(null, evtType.DownloadFileError, null);236 _this.emit(evtType.ProtocolMessage, Obj);237 resolve(obj);238 }239 });240 };241 UpdateClass.prototype.DownloadInstallPackage = function (callback) {242 env.log('UpdateClass','UpdateClass','DownloadInstallPackage')243 try{244 var packPath = os.tmpdir()+"/"+AppData.AppSettingData.ProjectName+".zip";245 _this.DownloadFileCancel = false;246 env.log('UpdateClass','DownloadInstallPackage',`package:${packPath}`); 247 var pathExt = path.extname(packPath).toLowerCase();248 var dirName = path.join(path.dirname(packPath), 'GSPYUpdate'); 249 if (fs.existsSync(dirName)){250 env.DeleteFolderRecursive(dirName, false);251 }else{252 fs.mkdirSync(dirName);253 }254 const {shell} = require('electron');255 if(env.isMac && pathExt === '.zip'){256 cp.execFile('/usr/bin/unzip',['-q','-o',packPath,'-d',dirName],[],function(err, stdout, stderr){257 if(err != undefined && err != null){258 env.log('Error','DownloadInstallPackage',`upzip error : ${err}`);259 }260 if(stderr != undefined && stderr != null){261 env.log('Error','DownloadInstallPackage',`upzip error :`+stderr);262 }263 var baseName = GetExtFilePath(dirName, '.mpkg');264 if (baseName === undefined){265 baseName = GetExtFilePath(dirName, '.pkg');266 }267 if (baseName === undefined){268 env.log('Error','DownloadInstallPackage',`Not found .mpkg file in:${dirName}`);269 callback(0x1008);270 return;271 }272 cp.execFile('/bin/chmod',['777',baseName],[],function(err, stdout, stderr){273 if(err!=undefined && err!=null){274 env.log('Error','DownloadInstallPackage',`chomd error:${err}`); 275 }276 if(stderr != undefined && stderr != null){277 env.log('Error','DownloadInstallPackage',`chomd error:${stderr}`);278 }279 fs.unlink(packPath,function() {280 env.log('UpdateClass','DownloadInstallPackage',`run insPack:${baseName}`);281 shell.openItem(baseName);282 callback();283 });284 });285 });286 }else if(env.isWindows && pathExt === '.zip'){287 try288 { 289 var AdmZip = require('adm-zip');290 var zip = new AdmZip(packPath);291 zip.extractAllTo(dirName, true);292 var baseName = GetExtFilePath(dirName, '.exe');293 if (baseName === undefined){294 env.log('Error','DownloadInstallPackage',`Not found .exe file in ${dirName}`);295 callback(0x1008);296 return;297 }298 fs.unlink(packPath,function () 299 {300 env.log('UpdateClass','DownloadInstallPackage',`run insPack:${dirName}`);301 try302 {303 shell.openItem(baseName);304 }catch(e){ 305 env.log('Error','openItem error : ',e);306 } 307 callback();308 });309 }catch(e){310 env.log('UpdateClass','openItem : ',e.toString());311 } 312 }313 }catch(ex){314 env.log('Error','DownloadInstallPackage',`ex:${ex.message}`);315 callback(0x1008);316 }317 };318 UpdateClass.prototype.UpdateFW = function () {319 env.log('UpdateClass','UpdateClass','UpdateFW');320 return new Promise(function(resolve,reject){321 try{322 if(env.isMac && fs.existsSync(os.tmpdir()+"/GSPYFWUpdate"))323 {324 var Obj={325 Type : funcVar.FuncType.System,326 Func : evtType.UpdateFW,327 Param : 0328 };329 _this.emit(evtType.ProtocolMessage, Obj);330 return resolve();331 }332 else if(env.isWindows && fs.existsSync(os.tmpdir()+"\\"+"GSPYFWUpdate")){333 var Obj={334 Type : funcVar.FuncType.System,335 SN : null,336 Func : evtType.UpdateFW,337 Param : 0338 };339 _this.emit(evtType.ProtocolMessage, Obj);340 return resolve();341 }342 request.get(AppData.AppSettingData.UpdateUrl+'/UpdateApp.json',function(err, resp, body){343 var body = JSON.parse(body);344 if(body.hasOwnProperty('FWVersion') && env.CompareVersion(AppData.AppSettingData.FWVersion,body.FWVersion)){345 var fromFile;346 var toFile; 347 if(env.isWindows){348 fromFile = AppData.AppSettingData.UpdateUrl+body.FWName.Win;349 toFile = os.tmpdir()+"\\"+AppData.AppSettingData.ProjectName+"FW.zip";350 }351 else{352 fromFile = AppData.AppSettingData.UpdateUrl+body.FWName.Mac;353 toFile = os.tmpdir()+"/"+AppData.AppSettingData.ProjectName+"FW.zip";354 }355 _this.DownloadFileFromURL(fromFile, toFile, true).then(function(obj){356 // _this.DownloadFWInstallPackage(function(){357 env.log('UpdateClass','UpdateApp','DownloadFileFromURL success');358 var Obj={359 Type : funcVar.FuncType.System,360 SN : null,361 Func : evtType.UpdateFW,362 Param : 0363 };364 365 _this.emit(evtType.ProtocolMessage, Obj);366 resolve();367 // })368 })369 }else{370 env.log('UpdateClass','UpdateApp','DownloadFileFromURL fail');371 resolve();372 }373 })374 }catch(ex){375 reject(ex);376 }377 });378 }379 UpdateClass.prototype.DownloadFWInstallPackage = function (callback) {380 env.log('UpdateClass','UpdateClass','DownloadInstallPackage')381 try{382 var packPath = os.tmpdir()+"/"+AppData.AppSettingData.ProjectName+"FW.zip";383 _this.DownloadFileCancel = false;384 env.log('UpdateClass','DownloadInstallPackage',`package:${packPath}`); 385 var pathExt = path.extname(packPath).toLowerCase();386 var dirName = path.join(path.dirname(packPath), 'GSPYFWUpdate'); 387 if (fs.existsSync(dirName)){388 env.DeleteFolderRecursive(dirName, false);389 }else{390 fs.mkdirSync(dirName);391 }392 const {shell} = require('electron');393 if(env.isMac && pathExt === '.zip'){394 cp.execFile('/usr/bin/unzip',['-q','-o',packPath,'-d',dirName],[],function(err, stdout, stderr){395 if(err != undefined && err != null){396 env.log('Error','DownloadInstallPackage',`upzip error : ${err}`);397 }398 if(stderr != undefined && stderr != null){399 env.log('Error','DownloadInstallPackage',`upzip error :`+stderr);400 }401 var baseName = GetExtFilePath(dirName, '.mpkg');402 if (baseName === undefined){403 baseName = GetExtFilePath(dirName, '.pkg');404 }405 if (baseName === undefined){406 env.log('Error','DownloadInstallPackage',`Not found .mpkg file in:${dirName}`);407 callback(0x1008);408 return;409 }410 cp.execFile('/bin/chmod',['777',baseName],[],function(err, stdout, stderr){411 if(err!=undefined && err!=null){412 env.log('Error','DownloadInstallPackage',`chomd error:${err}`); 413 }414 if(stderr != undefined && stderr != null){415 env.log('Error','DownloadInstallPackage',`chomd error:${stderr}`);416 }417 fs.unlink(packPath,function() {418 env.log('UpdateClass','DownloadInstallPackage',`run insPack:${baseName}`);419 shell.openItem(baseName);420 callback();421 });422 });423 });424 }else if(env.isWindows && pathExt === '.zip'){425 try426 { 427 var AdmZip = require('adm-zip');428 var zip = new AdmZip(packPath);429 zip.extractAllTo(dirName, true);430 var baseName = GetExtFilePath(dirName, '.exe');431 if (baseName === undefined){432 env.log('Error','DownloadInstallPackage',`Not found .exe file in ${dirName}`);433 callback(0x1008);434 return;435 }436 fs.unlink(packPath,function () 437 {438 env.log('UpdateClass','DownloadInstallPackage',`run insPack:${dirName}`);439 try440 {441 shell.openItem(baseName);442 }catch(e){ 443 env.log('Error','openItem error : ',e);444 } 445 callback();446 });447 }catch(e){448 env.log('UpdateClass','openItem : ',e.toString());449 } 450 }451 }catch(ex){452 env.log('Error','DownloadInstallPackage',`ex:${ex.message}`);453 callback(0x1008);454 }455 };456 457 return UpdateClass;458})(events.EventEmitter);...
flowUpdate.test.js
Source:flowUpdate.test.js
1/* eslint-disable no-await-in-loop */2const { setup, tearDown } = require('./helpers');3const {4 Project,5 UpdateTypes,6 Roles,7 Update,8 FlowUpdate9} = require('models');10const UpdateClass = FlowUpdate;11const project = new Project('1', {12 name: "My project",13 description: "A description",14 updateTypes: [UpdateTypes.insights],15 teams: [],16 roles: {17 'owner@example.org': Roles.owner,18 'admin@example.org': Roles.administrator,19 'author@example.org': Roles.author,20 'member@example.org': Roles.member,21 }22});23const owner = {uid: '1', email: 'owner@example.org'},24 admin = {uid: '2', email: 'admin@example.org'},25 author = {uid: '3', email: 'author@example.org'},26 member = {uid: '4', email: 'member@example.org'};27const u1 = new UpdateClass('1', {28 title: "My update",29 summary: "An update",30 date: new Date(2020, 1, 1),31 team: "Alpha",32 33 cycleTimeData: [{34 commitmentDate: new Date(2020, 1, 1),35 completionDate: null,36 item: "Hello",37 itemType: null,38 url: null39 }]40 }, project);41// everything below should in theory be the same for all update types42afterAll(async () => {43 await tearDown();44});45describe('security', () => {46 test('owner can create, read, update, delete', async () => {47 const db = await setup(owner, {48 [project.getPath()]: Project.toFirestore(project),49 [u1.getPath()]: Update.toFirestore(u1)50 });51 await expect(52 db.collection(Update.getCollectionPath(project))53 .withConverter(Update)54 .add(new UpdateClass(null, u1.toObject(), project))55 ).toBeAllowed();56 await expect(db.doc(u1.getPath()).get()).toBeAllowed();57 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();58 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();59 });60 test('admin can create, read, update, delete', async () => {61 const db = await setup(admin, {62 [project.getPath()]: Project.toFirestore(project),63 [u1.getPath()]: Update.toFirestore(u1)64 });65 await expect(66 db.collection(Update.getCollectionPath(project))67 .withConverter(Update)68 .add(new UpdateClass(null, u1.toObject(), project))69 ).toBeAllowed();70 await expect(db.doc(u1.getPath()).get()).toBeAllowed();71 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();72 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();73 });74 test('author can create, read, update, delete', async () => {75 const db = await setup(author, {76 [project.getPath()]: Project.toFirestore(project),77 [u1.getPath()]: Update.toFirestore(u1)78 });79 await expect(80 db.collection(Update.getCollectionPath(project))81 .withConverter(Update)82 .add(new UpdateClass(null, u1.toObject(), project))83 ).toBeAllowed();84 await expect(db.doc(u1.getPath()).get()).toBeAllowed();85 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();86 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();87 });88 test('member can only read', async () => {89 const db = await setup(member, {90 [project.getPath()]: Project.toFirestore(project),91 [u1.getPath()]: Update.toFirestore(u1)92 });93 await expect(94 db.collection(Update.getCollectionPath(project))95 .withConverter(Update)96 .add(new UpdateClass(null, u1.toObject(), project))97 ).toBeDenied();98 await expect(db.doc(u1.getPath()).get()).toBeAllowed();99 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeDenied();100 await expect(db.doc(u1.getPath()).delete()).toBeDenied();101 });102 103});104describe('conversion', () => {105 test('round trip write and read with type lookup', async () => {106 const db = await setup(owner, {107 [project.getPath()]: Project.toFirestore(project),108 });109 const u2 = new UpdateClass('2', u1.toObject(), project);110 await db.doc(u2.getPath()).withConverter(Update).set(u2);111 const u3 = (await db.doc(u2.getPath()).withConverter(Update).get()).data();112 113 expect(u3.constructor).toEqual(UpdateClass);114 expect(u3.toObject()).toEqual(u2.toObject());115 });116 test('recovery of broken object (invalid title)', async () => {117 const db = await setup(owner, {118 [project.getPath()]: Project.toFirestore(project),119 [u1.getPath()]: {120 ...Update.toFirestore(u1),121 title: null,122 date: "Foo",123 cycleTimeData: null124 }125 });126 // hide expected error logging127 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});128 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();129 spy.mockRestore();130 expect(u2.constructor).toEqual(UpdateClass);131 expect(u2.error).toBeTruthy();132 expect(u2.toObject()).toEqual({133 ...Update.toFirestore(u1),134 title: null,135 date: "Foo",136 cycleTimeData: null137 });138 139 });140 test('recovery of broken object (invalid type)', async () => {141 const db = await setup(owner, {142 [project.getPath()]: Project.toFirestore(project),143 [u1.getPath()]: {144 ...Update.toFirestore(u1),145 type: 'not-valid'146 }147 });148 // hide expected error logging149 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});150 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();151 spy.mockRestore();152 expect(u2.constructor).toEqual(Update);153 expect(u2.error).toBeTruthy();154 expect(u2.title).toEqual(u1.title);155 expect(u2.type).toEqual('not-valid');156 });157});158describe('validation', () => {159 test('must have all required keys', async () => {160 const db = await setup(owner, {161 [project.getPath()]: Project.toFirestore(project),162 [u1.getPath()]: Update.toFirestore(u1)163 });164 const requiredKeys = Object.entries(UpdateClass.getSchema().fields).filter(([k, v]) => v._exclusive.required).map(([k, v]) => k);165 for(let key of requiredKeys) {166 let data = {...u1.toObject()};167 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeAllowed();168 await expect(db.doc(u1.getPath()).set(data)).toBeAllowed();169 170 delete data[key];171 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeDenied();172 await expect(db.doc(u1.getPath()).set(data)).toBeDenied();173 }174 });175 test('cannot have unknown keys', async () => {176 const db = await setup(owner, {177 [project.getPath()]: Project.toFirestore(project),178 [u1.getPath()]: Update.toFirestore(u1)179 });180 const ringer = {ringer: 1};181 const valid = u1.toObject();182 const invalid = {...valid, ...ringer};183 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();184 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();185 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();186 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();187 });188 test('must have a valid update type', async () => {189 const db = await setup(owner, {190 [project.getPath()]: Project.toFirestore(project),191 [u1.getPath()]: Update.toFirestore(u1)192 });193 const ringer = {type: 'not-valid'};194 const valid = u1.toObject();195 const invalid = {...valid, ...ringer};196 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();197 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();198 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();199 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();200 });201 test('must have a string title', async () => {202 const db = await setup(owner, {203 [project.getPath()]: Project.toFirestore(project),204 [u1.getPath()]: Update.toFirestore(u1)205 });206 const ringer = {title: false};207 const valid = u1.toObject();208 const invalid = {...valid, ...ringer};209 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();210 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();211 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();212 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();213 });214 test('must have a string summary', async () => {215 const db = await setup(owner, {216 [project.getPath()]: Project.toFirestore(project),217 [u1.getPath()]: Update.toFirestore(u1)218 });219 const ringer = {summary: 123};220 const valid = u1.toObject();221 const invalid = {...valid, ...ringer};222 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();223 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();224 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();225 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();226 });227 test('must have a timestamp date', async () => {228 const db = await setup(owner, {229 [project.getPath()]: Project.toFirestore(project),230 [u1.getPath()]: Update.toFirestore(u1)231 });232 const ringer = {date: "yesterday"};233 const valid = u1.toObject();234 const invalid = {...valid, ...ringer};235 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();236 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();237 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();238 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();239 });240 test('must have a null or string team', async () => {241 const db = await setup(owner, {242 [project.getPath()]: Project.toFirestore(project),243 [u1.getPath()]: Update.toFirestore(u1)244 });245 const ringer = {team: true};246 const valid = {...u1.toObject(), team: null};247 const invalid = {...valid, ...ringer};248 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();249 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();250 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();251 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();252 });...
raidUpdate.test.js
Source:raidUpdate.test.js
1/* eslint-disable no-await-in-loop */2const { setup, tearDown } = require('./helpers');3const {4 Project,5 UpdateTypes,6 Roles,7 Update,8 RaidUpdate9} = require('models');10const UpdateClass = RaidUpdate;11const project = new Project('1', {12 name: "My project",13 description: "A description",14 updateTypes: [UpdateTypes.insights],15 teams: [],16 roles: {17 'owner@example.org': Roles.owner,18 'admin@example.org': Roles.administrator,19 'author@example.org': Roles.author,20 'member@example.org': Roles.member,21 }22});23const owner = {uid: '1', email: 'owner@example.org'},24 admin = {uid: '2', email: 'admin@example.org'},25 author = {uid: '3', email: 'author@example.org'},26 member = {uid: '4', email: 'member@example.org'};27const u1 = new UpdateClass('1', {28 title: "My update",29 summary: "An update",30 date: new Date(2020, 1, 1),31 team: "Alpha",32 33 raidItems: [{34 type: 'risk',35 summary: "A risk",36 url: null,37 priority: 'medium',38 date: new Date(2020, 2, 1)39 }]40 }, project);41// everything below should in theory be the same for all update types42afterAll(async () => {43 await tearDown();44});45describe('security', () => {46 test('owner can create, read, update, delete', async () => {47 const db = await setup(owner, {48 [project.getPath()]: Project.toFirestore(project),49 [u1.getPath()]: Update.toFirestore(u1)50 });51 await expect(52 db.collection(Update.getCollectionPath(project))53 .withConverter(Update)54 .add(new UpdateClass(null, u1.toObject(), project))55 ).toBeAllowed();56 await expect(db.doc(u1.getPath()).get()).toBeAllowed();57 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();58 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();59 });60 test('admin can create, read, update, delete', async () => {61 const db = await setup(admin, {62 [project.getPath()]: Project.toFirestore(project),63 [u1.getPath()]: Update.toFirestore(u1)64 });65 await expect(66 db.collection(Update.getCollectionPath(project))67 .withConverter(Update)68 .add(new UpdateClass(null, u1.toObject(), project))69 ).toBeAllowed();70 await expect(db.doc(u1.getPath()).get()).toBeAllowed();71 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();72 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();73 });74 test('author can create, read, update, delete', async () => {75 const db = await setup(author, {76 [project.getPath()]: Project.toFirestore(project),77 [u1.getPath()]: Update.toFirestore(u1)78 });79 await expect(80 db.collection(Update.getCollectionPath(project))81 .withConverter(Update)82 .add(new UpdateClass(null, u1.toObject(), project))83 ).toBeAllowed();84 await expect(db.doc(u1.getPath()).get()).toBeAllowed();85 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();86 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();87 });88 test('member can only read', async () => {89 const db = await setup(member, {90 [project.getPath()]: Project.toFirestore(project),91 [u1.getPath()]: Update.toFirestore(u1)92 });93 await expect(94 db.collection(Update.getCollectionPath(project))95 .withConverter(Update)96 .add(new UpdateClass(null, u1.toObject(), project))97 ).toBeDenied();98 await expect(db.doc(u1.getPath()).get()).toBeAllowed();99 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeDenied();100 await expect(db.doc(u1.getPath()).delete()).toBeDenied();101 });102 103});104describe('conversion', () => {105 test('round trip write and read with type lookup', async () => {106 const db = await setup(owner, {107 [project.getPath()]: Project.toFirestore(project),108 });109 const u2 = new UpdateClass('2', u1.toObject(), project);110 await db.doc(u2.getPath()).withConverter(Update).set(u2);111 const u3 = (await db.doc(u2.getPath()).withConverter(Update).get()).data();112 113 expect(u3.constructor).toEqual(UpdateClass);114 expect(u3.toObject()).toEqual(u2.toObject());115 });116 test('recovery of broken object (invalid title)', async () => {117 const db = await setup(owner, {118 [project.getPath()]: Project.toFirestore(project),119 [u1.getPath()]: {120 ...Update.toFirestore(u1),121 title: null,122 date: "Foo",123 raidItems: null124 }125 });126 // hide expected error logging127 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});128 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();129 spy.mockRestore();130 expect(u2.constructor).toEqual(UpdateClass);131 expect(u2.error).toBeTruthy();132 expect(u2.toObject()).toEqual({133 ...Update.toFirestore(u1),134 title: null,135 date: "Foo",136 raidItems: null137 });138 139 });140 test('recovery of broken object (invalid type)', async () => {141 const db = await setup(owner, {142 [project.getPath()]: Project.toFirestore(project),143 [u1.getPath()]: {144 ...Update.toFirestore(u1),145 type: 'not-valid'146 }147 });148 // hide expected error logging149 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});150 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();151 spy.mockRestore();152 expect(u2.constructor).toEqual(Update);153 expect(u2.error).toBeTruthy();154 expect(u2.title).toEqual(u1.title);155 expect(u2.type).toEqual('not-valid');156 });157});158describe('validation', () => {159 test('must have all required keys', async () => {160 const db = await setup(owner, {161 [project.getPath()]: Project.toFirestore(project),162 [u1.getPath()]: Update.toFirestore(u1)163 });164 const requiredKeys = Object.entries(UpdateClass.getSchema().fields).filter(([k, v]) => v._exclusive.required).map(([k, v]) => k);165 for(let key of requiredKeys) {166 let data = {...u1.toObject()};167 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeAllowed();168 await expect(db.doc(u1.getPath()).set(data)).toBeAllowed();169 170 delete data[key];171 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeDenied();172 await expect(db.doc(u1.getPath()).set(data)).toBeDenied();173 }174 });175 test('cannot have unknown keys', async () => {176 const db = await setup(owner, {177 [project.getPath()]: Project.toFirestore(project),178 [u1.getPath()]: Update.toFirestore(u1)179 });180 const ringer = {ringer: 1};181 const valid = u1.toObject();182 const invalid = {...valid, ...ringer};183 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();184 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();185 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();186 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();187 });188 test('must have a valid update type', async () => {189 const db = await setup(owner, {190 [project.getPath()]: Project.toFirestore(project),191 [u1.getPath()]: Update.toFirestore(u1)192 });193 const ringer = {type: 'not-valid'};194 const valid = u1.toObject();195 const invalid = {...valid, ...ringer};196 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();197 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();198 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();199 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();200 });201 test('must have a string title', async () => {202 const db = await setup(owner, {203 [project.getPath()]: Project.toFirestore(project),204 [u1.getPath()]: Update.toFirestore(u1)205 });206 const ringer = {title: false};207 const valid = u1.toObject();208 const invalid = {...valid, ...ringer};209 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();210 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();211 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();212 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();213 });214 test('must have a string summary', async () => {215 const db = await setup(owner, {216 [project.getPath()]: Project.toFirestore(project),217 [u1.getPath()]: Update.toFirestore(u1)218 });219 const ringer = {summary: 123};220 const valid = u1.toObject();221 const invalid = {...valid, ...ringer};222 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();223 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();224 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();225 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();226 });227 test('must have a timestamp date', async () => {228 const db = await setup(owner, {229 [project.getPath()]: Project.toFirestore(project),230 [u1.getPath()]: Update.toFirestore(u1)231 });232 const ringer = {date: "yesterday"};233 const valid = u1.toObject();234 const invalid = {...valid, ...ringer};235 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();236 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();237 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();238 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();239 });240 test('must have a null or string team', async () => {241 const db = await setup(owner, {242 [project.getPath()]: Project.toFirestore(project),243 [u1.getPath()]: Update.toFirestore(u1)244 });245 const ringer = {team: true};246 const valid = {...u1.toObject(), team: null};247 const invalid = {...valid, ...ringer};248 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();249 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();250 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();251 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();252 });...
insightsUpdate.test.js
Source:insightsUpdate.test.js
1/* eslint-disable no-await-in-loop */2const { setup, tearDown } = require('./helpers');3const {4 Project,5 UpdateTypes,6 Roles,7 Update,8 InsightsUpdate9} = require('models');10const UpdateClass = InsightsUpdate;11const project = new Project('1', {12 name: "My project",13 description: "A description",14 updateTypes: [UpdateTypes.insights],15 teams: [],16 roles: {17 'owner@example.org': Roles.owner,18 'admin@example.org': Roles.administrator,19 'author@example.org': Roles.author,20 'member@example.org': Roles.member,21 }22});23const owner = {uid: '1', email: 'owner@example.org'},24 admin = {uid: '2', email: 'admin@example.org'},25 author = {uid: '3', email: 'author@example.org'},26 member = {uid: '4', email: 'member@example.org'};27const u1 = new UpdateClass('1', {28 title: "My update",29 summary: "An update",30 date: new Date(2020, 1, 1),31 team: "Alpha",32 33 authorId: '1',34 authorName: 'John',35 text: 'Some text'36 }, project);37// everything below should in theory be the same for all update types38afterAll(async () => {39 await tearDown();40});41describe('security', () => {42 test('owner can create, read, update, delete', async () => {43 const db = await setup(owner, {44 [project.getPath()]: Project.toFirestore(project),45 [u1.getPath()]: Update.toFirestore(u1)46 });47 await expect(48 db.collection(Update.getCollectionPath(project))49 .withConverter(Update)50 .add(new UpdateClass(null, u1.toObject(), project))51 ).toBeAllowed();52 await expect(db.doc(u1.getPath()).get()).toBeAllowed();53 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();54 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();55 });56 test('admin can create, read, update, delete', async () => {57 const db = await setup(admin, {58 [project.getPath()]: Project.toFirestore(project),59 [u1.getPath()]: Update.toFirestore(u1)60 });61 await expect(62 db.collection(Update.getCollectionPath(project))63 .withConverter(Update)64 .add(new UpdateClass(null, u1.toObject(), project))65 ).toBeAllowed();66 await expect(db.doc(u1.getPath()).get()).toBeAllowed();67 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();68 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();69 });70 test('author can create, read, update, delete', async () => {71 const db = await setup(author, {72 [project.getPath()]: Project.toFirestore(project),73 [u1.getPath()]: Update.toFirestore(u1)74 });75 await expect(76 db.collection(Update.getCollectionPath(project))77 .withConverter(Update)78 .add(new UpdateClass(null, u1.toObject(), project))79 ).toBeAllowed();80 await expect(db.doc(u1.getPath()).get()).toBeAllowed();81 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();82 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();83 });84 test('member can only read', async () => {85 const db = await setup(member, {86 [project.getPath()]: Project.toFirestore(project),87 [u1.getPath()]: Update.toFirestore(u1)88 });89 await expect(90 db.collection(Update.getCollectionPath(project))91 .withConverter(Update)92 .add(new UpdateClass(null, u1.toObject(), project))93 ).toBeDenied();94 await expect(db.doc(u1.getPath()).get()).toBeAllowed();95 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeDenied();96 await expect(db.doc(u1.getPath()).delete()).toBeDenied();97 });98 99});100describe('conversion', () => {101 test('round trip write and read with type lookup', async () => {102 const db = await setup(owner, {103 [project.getPath()]: Project.toFirestore(project),104 });105 const u2 = new UpdateClass('2', u1.toObject(), project);106 await db.doc(u2.getPath()).withConverter(Update).set(u2);107 const u3 = (await db.doc(u2.getPath()).withConverter(Update).get()).data();108 109 expect(u3.constructor).toEqual(UpdateClass);110 expect(u3.toObject()).toEqual(u2.toObject());111 });112 test('recovery of broken object (invalid title)', async () => {113 const db = await setup(owner, {114 [project.getPath()]: Project.toFirestore(project),115 [u1.getPath()]: {116 ...Update.toFirestore(u1),117 date: "foo",118 title: null119 }120 });121 // hide expected error logging122 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});123 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();124 spy.mockRestore();125 expect(u2.constructor).toEqual(UpdateClass);126 expect(u2.error).toBeTruthy();127 expect(u2.toObject()).toEqual({128 ...Update.toFirestore(u1),129 date: "foo",130 title: null131 });132 133 });134 test('recovery of broken object (invalid type)', async () => {135 const db = await setup(owner, {136 [project.getPath()]: Project.toFirestore(project),137 [u1.getPath()]: {138 ...Update.toFirestore(u1),139 type: 'not-valid'140 }141 });142 // hide expected error logging143 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});144 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();145 spy.mockRestore();146 expect(u2.constructor).toEqual(Update);147 expect(u2.error).toBeTruthy();148 expect(u2.title).toEqual(u1.title);149 expect(u2.type).toEqual('not-valid');150 });151});152describe('validation', () => {153 test('must have all required keys', async () => {154 const db = await setup(owner, {155 [project.getPath()]: Project.toFirestore(project),156 [u1.getPath()]: Update.toFirestore(u1)157 });158 const requiredKeys = Object.entries(UpdateClass.getSchema().fields).filter(([k, v]) => v._exclusive.required).map(([k, v]) => k);159 for(let key of requiredKeys) {160 let data = {...u1.toObject()};161 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeAllowed();162 await expect(db.doc(u1.getPath()).set(data)).toBeAllowed();163 164 delete data[key];165 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeDenied();166 await expect(db.doc(u1.getPath()).set(data)).toBeDenied();167 }168 });169 test('cannot have unknown keys', async () => {170 const db = await setup(owner, {171 [project.getPath()]: Project.toFirestore(project),172 [u1.getPath()]: Update.toFirestore(u1)173 });174 const ringer = {ringer: 1};175 const valid = u1.toObject();176 const invalid = {...valid, ...ringer};177 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();178 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();179 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();180 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();181 });182 test('must have a valid update type', async () => {183 const db = await setup(owner, {184 [project.getPath()]: Project.toFirestore(project),185 [u1.getPath()]: Update.toFirestore(u1)186 });187 const ringer = {type: 'not-valid'};188 const valid = u1.toObject();189 const invalid = {...valid, ...ringer};190 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();191 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();192 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();193 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();194 });195 test('must have a string title', async () => {196 const db = await setup(owner, {197 [project.getPath()]: Project.toFirestore(project),198 [u1.getPath()]: Update.toFirestore(u1)199 });200 const ringer = {title: false};201 const valid = u1.toObject();202 const invalid = {...valid, ...ringer};203 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();204 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();205 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();206 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();207 });208 test('must have a string summary', async () => {209 const db = await setup(owner, {210 [project.getPath()]: Project.toFirestore(project),211 [u1.getPath()]: Update.toFirestore(u1)212 });213 const ringer = {summary: 123};214 const valid = u1.toObject();215 const invalid = {...valid, ...ringer};216 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();217 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();218 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();219 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();220 });221 test('must have a timestamp date', async () => {222 const db = await setup(owner, {223 [project.getPath()]: Project.toFirestore(project),224 [u1.getPath()]: Update.toFirestore(u1)225 });226 const ringer = {date: "yesterday"};227 const valid = u1.toObject();228 const invalid = {...valid, ...ringer};229 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();230 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();231 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();232 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();233 });234 test('must have a null or string team', async () => {235 const db = await setup(owner, {236 [project.getPath()]: Project.toFirestore(project),237 [u1.getPath()]: Update.toFirestore(u1)238 });239 const ringer = {team: true};240 const valid = {...u1.toObject(), team: null};241 const invalid = {...valid, ...ringer};242 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();243 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();244 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();245 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();246 });...
goalsUpdate.test.js
Source:goalsUpdate.test.js
1/* eslint-disable no-await-in-loop */2const { setup, tearDown } = require('./helpers');3const {4 Project,5 UpdateTypes,6 Roles,7 Update,8 GoalsUpdate9} = require('models');10const UpdateClass = GoalsUpdate;11const project = new Project('1', {12 name: "My project",13 description: "A description",14 updateTypes: [UpdateTypes.insights],15 teams: [],16 roles: {17 'owner@example.org': Roles.owner,18 'admin@example.org': Roles.administrator,19 'author@example.org': Roles.author,20 'member@example.org': Roles.member,21 }22});23const owner = {uid: '1', email: 'owner@example.org'},24 admin = {uid: '2', email: 'admin@example.org'},25 author = {uid: '3', email: 'author@example.org'},26 member = {uid: '4', email: 'member@example.org'};27const u1 = new UpdateClass('1', {28 title: "My update",29 summary: "An update",30 date: new Date(2020, 1, 1),31 team: "Alpha",32 33 authorId: '1',34 authorName: 'John',35 text: 'Some text'36 }, project);37// everything below should in theory be the same for all update types38afterAll(async () => {39 await tearDown();40});41describe('security', () => {42 test('owner can create, read, update, delete', async () => {43 const db = await setup(owner, {44 [project.getPath()]: Project.toFirestore(project),45 [u1.getPath()]: Update.toFirestore(u1)46 });47 await expect(48 db.collection(Update.getCollectionPath(project))49 .withConverter(Update)50 .add(new UpdateClass(null, u1.toObject(), project))51 ).toBeAllowed();52 await expect(db.doc(u1.getPath()).get()).toBeAllowed();53 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();54 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();55 });56 test('admin can create, read, update, delete', async () => {57 const db = await setup(admin, {58 [project.getPath()]: Project.toFirestore(project),59 [u1.getPath()]: Update.toFirestore(u1)60 });61 await expect(62 db.collection(Update.getCollectionPath(project))63 .withConverter(Update)64 .add(new UpdateClass(null, u1.toObject(), project))65 ).toBeAllowed();66 await expect(db.doc(u1.getPath()).get()).toBeAllowed();67 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();68 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();69 });70 test('author can create, read, update, delete', async () => {71 const db = await setup(author, {72 [project.getPath()]: Project.toFirestore(project),73 [u1.getPath()]: Update.toFirestore(u1)74 });75 await expect(76 db.collection(Update.getCollectionPath(project))77 .withConverter(Update)78 .add(new UpdateClass(null, u1.toObject(), project))79 ).toBeAllowed();80 await expect(db.doc(u1.getPath()).get()).toBeAllowed();81 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeAllowed();82 await expect(db.doc(u1.getPath()).delete()).toBeAllowed();83 });84 test('member can only read', async () => {85 const db = await setup(member, {86 [project.getPath()]: Project.toFirestore(project),87 [u1.getPath()]: Update.toFirestore(u1)88 });89 await expect(90 db.collection(Update.getCollectionPath(project))91 .withConverter(Update)92 .add(new UpdateClass(null, u1.toObject(), project))93 ).toBeDenied();94 await expect(db.doc(u1.getPath()).get()).toBeAllowed();95 await expect(db.doc(u1.getPath()).update({title: 'Changed update'})).toBeDenied();96 await expect(db.doc(u1.getPath()).delete()).toBeDenied();97 });98 99});100describe('conversion', () => {101 test('round trip write and read with type lookup', async () => {102 const db = await setup(owner, {103 [project.getPath()]: Project.toFirestore(project),104 });105 const u2 = new UpdateClass('2', u1.toObject(), project);106 await db.doc(u2.getPath()).withConverter(Update).set(u2);107 const u3 = (await db.doc(u2.getPath()).withConverter(Update).get()).data();108 109 expect(u3.constructor).toEqual(UpdateClass);110 expect(u3.toObject()).toEqual(u2.toObject());111 });112 test('recovery of broken object (invalid title)', async () => {113 const db = await setup(owner, {114 [project.getPath()]: Project.toFirestore(project),115 [u1.getPath()]: {116 ...Update.toFirestore(u1),117 date: "foo",118 title: null119 }120 });121 // hide expected error logging122 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});123 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();124 spy.mockRestore();125 expect(u2.constructor).toEqual(UpdateClass);126 expect(u2.error).toBeTruthy();127 expect(u2.toObject()).toEqual({128 ...Update.toFirestore(u1),129 date: "foo",130 title: null131 });132 133 });134 test('recovery of broken object (invalid type)', async () => {135 const db = await setup(owner, {136 [project.getPath()]: Project.toFirestore(project),137 [u1.getPath()]: {138 ...Update.toFirestore(u1),139 type: 'not-valid'140 }141 });142 // hide expected error logging143 const spy = jest.spyOn(console, 'error').mockImplementation(() => {});144 const u2 = (await db.doc(u1.getPath()).withConverter(Update).get()).data();145 spy.mockRestore();146 expect(u2.constructor).toEqual(Update);147 expect(u2.error).toBeTruthy();148 expect(u2.title).toEqual(u1.title);149 expect(u2.type).toEqual('not-valid');150 });151});152describe('validation', () => {153 test('must have all required keys', async () => {154 const db = await setup(owner, {155 [project.getPath()]: Project.toFirestore(project),156 [u1.getPath()]: Update.toFirestore(u1)157 });158 const requiredKeys = Object.entries(UpdateClass.getSchema().fields).filter(([k, v]) => v._exclusive.required).map(([k, v]) => k);159 for(let key of requiredKeys) {160 let data = {...u1.toObject()};161 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeAllowed();162 await expect(db.doc(u1.getPath()).set(data)).toBeAllowed();163 164 delete data[key];165 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(data)).toBeDenied();166 await expect(db.doc(u1.getPath()).set(data)).toBeDenied();167 }168 });169 test('cannot have unknown keys', async () => {170 const db = await setup(owner, {171 [project.getPath()]: Project.toFirestore(project),172 [u1.getPath()]: Update.toFirestore(u1)173 });174 const ringer = {ringer: 1};175 const valid = u1.toObject();176 const invalid = {...valid, ...ringer};177 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();178 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();179 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();180 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();181 });182 test('must have a valid update type', async () => {183 const db = await setup(owner, {184 [project.getPath()]: Project.toFirestore(project),185 [u1.getPath()]: Update.toFirestore(u1)186 });187 const ringer = {type: 'not-valid'};188 const valid = u1.toObject();189 const invalid = {...valid, ...ringer};190 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();191 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();192 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();193 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();194 });195 test('must have a string title', async () => {196 const db = await setup(owner, {197 [project.getPath()]: Project.toFirestore(project),198 [u1.getPath()]: Update.toFirestore(u1)199 });200 const ringer = {title: false};201 const valid = u1.toObject();202 const invalid = {...valid, ...ringer};203 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();204 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();205 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();206 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();207 });208 test('must have a string summary', async () => {209 const db = await setup(owner, {210 [project.getPath()]: Project.toFirestore(project),211 [u1.getPath()]: Update.toFirestore(u1)212 });213 const ringer = {summary: 123};214 const valid = u1.toObject();215 const invalid = {...valid, ...ringer};216 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();217 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();218 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();219 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();220 });221 test('must have a timestamp date', async () => {222 const db = await setup(owner, {223 [project.getPath()]: Project.toFirestore(project),224 [u1.getPath()]: Update.toFirestore(u1)225 });226 const ringer = {date: "yesterday"};227 const valid = u1.toObject();228 const invalid = {...valid, ...ringer};229 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();230 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();231 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();232 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();233 });234 test('must have a null or string team', async () => {235 const db = await setup(owner, {236 [project.getPath()]: Project.toFirestore(project),237 [u1.getPath()]: Update.toFirestore(u1)238 });239 const ringer = {team: true};240 const valid = {...u1.toObject(), team: null};241 const invalid = {...valid, ...ringer};242 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(valid)).toBeAllowed();243 await expect(db.collection(UpdateClass.getCollectionPath(project)).add(invalid)).toBeDenied();244 await expect(db.doc(u1.getPath()).update(valid)).toBeAllowed();245 await expect(db.doc(u1.getPath()).update(ringer)).toBeDenied();246 });...
worksheets-route.js
Source:worksheets-route.js
1const express = require('express')2const path = require('path')3const WorksheetsService = require('./worksheets-service')4const { requireAuth } = require('../middleware/jwt-auth')5const { json } = require('express')6const postsRouter = express.Router()7const jsonBodyParser = express.json()8postsRouter9 .route('/')10 // .get((req, res, next) => {11 // WorksheetsService.getAllPosts(req.app.get('db'))12 // .then(posts => {13 // res.json(posts)14 // })15 // .catch(next)16 // })17 .post(requireAuth, jsonBodyParser, async (req, res, next) => {18 const { worksheet_name, class_id, animation_scroll, animation_questions, reading } = req.body19 const newWorksheet = { worksheet_name, class_id, animation_scroll, animation_questions, reading }20 for (const [key, value] of Object.entries(newWorksheet)) {21 if (value == null) {22 return res.status(400).json({ error: `Missing '${key}' in request body` })23 }24 }25 const updateClass = await WorksheetsService.getClassById(req.app.get('db'), class_id)26 const newClass = {27 class_id: updateClass[0].class_id,28 class_name: updateClass[0].class_name,29 class_password: updateClass[0].class_password,30 students: updateClass[0].students,31 worksheets: (updateClass[0].worksheets + 1),32 modified: updateClass[0].modified,33 teacher_id: updateClass[0].teacher_id,34 }35 await WorksheetsService.updateWorksheetCount(36 req.app.get('db'),37 newClass,38 class_id39 )40 console.log(newClass, {41 class_id: updateClass[0].class_id,42 class_name: updateClass[0].class_name,43 class_password: updateClass[0].class_password,44 students: updateClass[0].students,45 worksheets: (updateClass[0].worksheets + 1),46 modified: updateClass[0].modified,47 teacher_id: updateClass[0].teacher_id,48 })49 WorksheetsService.insertPost(50 req.app.get('db'),51 newWorksheet52 )53 .then(post => {54 res55 .status(201)56 .location(path.posix.join(req.originalUrl, `/${post.worksheet_id}`))57 .json(post)58 })59 })60postsRouter61 .route('/:class_id')62 .all(requireAuth)63 .get((req, res, next) => {64 console.log(req.params.class_id)65 WorksheetsService.getByClass(req.app.get('db'), req.params.class_id)66 .then(posts => {67 res.status(200).json(posts)68 })69 .catch(next)70 })71postsRouter72 .route('/:post_id')73 .all(requireAuth)74 .delete((req, res, next) => {75 WorksheetsService.deletePost(76 req.app.get('db'),77 req.params.post_id78 )79 .then(() => {80 res.status(204).end()81 })82 .catch(next)83 })...
script.js
Source:script.js
1$(document).ready(function() {2 3 // format and display current date4 var cTime = moment().format("dddd, MMMM Do")5 $("#currentDay").append(cTime)6 // current hour 7 var milHour = moment().format("HH")8 // list of hours used in agenda 9 var businessHoursMil = ["09", "10", "11", "12", "13", "14", "15", "16", "17"]10// check local storage to recall previously saved text to add back to agenda11 var storedAgenda = JSON.parse(localStorage.getItem("agendaSave")) || [] ;12 console.log(storedAgenda, "storedAgenda")13 14 // loop to reapply any saved agenda items from local storage15 for (var i = 0; i < storedAgenda.length; i++) {16 var hour = storedAgenda[i].hour;17 var textBlock = $("#text-" + hour)18 textBlock.text(storedAgenda[i].text)19 $("#text-" + hour).append(textBlock)20 }21// onClick function to save text and hour selected to local storage22 $(".saveBtn").click(function() {23 var textSave = $.trim($(this).siblings("textarea").val());24 var newSave = {text: textSave, hour: this.id}25 storedAgenda.push(newSave)26 window.localStorage.setItem("agendaSave", JSON.stringify(storedAgenda))27 })28 // apply color by class based on current hour29 for (var i = 0; i < businessHoursMil.length; i++) {30 if (milHour == businessHoursMil[i]) {31 var updateClass = $("." + businessHoursMil[i]);32 updateClass.addClass("present");33 $("." + businessHoursMil[i]).append(updateClass)34 } 35 }36 // apply color by class based on previous hours37 for (var i = 0; i < businessHoursMil.length; i++) {38 if (milHour > businessHoursMil[i]) {39 var updateClass = $("." + businessHoursMil[i]);40 updateClass.addClass("past");41 $("." + businessHoursMil[i]).append(updateClass)42 }43 }44 // apply color by class based on future hours45 for (var i = 0; i < businessHoursMil.length; i++) {46 if (milHour < businessHoursMil[i]) {47 var updateClass = $("." + businessHoursMil[i]);48 updateClass.addClass("future");49 $("." + businessHoursMil[i]).append(updateClass)50 }51 }...
index.js
Source:index.js
1import Vue from 'vue'2import Router from 'vue-router'3import HelloWorld from '../components/HelloWorld'4import feedBack from '../components/feedBack/feedBack'5import insertStudent from '../components/insertStudent/insertStudent'6import releaseClass from '../components/releaseClass/releaseClass'7import selectSeats from '../components/selectSeats/selectSeats'8import updateClass from '../components/updateClass/updateClass'9import updateStudent from '../components/updateStudent/updateStudent'10import viewStudent from '../components/viewStudent/viewStudent'11import changePassword from '../components/changePassword/changePassword'12import admin from '../components/admin/admin'13import feedBackMessage from '../components/feedBackMessage/feedBackMessage'14Vue.use(Router)15export default new Router({16 routes: [17 {18 path: '/',19 // name: 'HelloWorld',20 component: HelloWorld21 },22 {23 path:'/feedBack',24 // name:'feedBack',25 component:feedBack26 },27 {28 path:'/insertStudent',29 // name:'insertStudent',30 component:insertStudent31 },32 {33 path:'/releaseClass',34 // name:'release-Class',35 component:releaseClass36 },37 {38 path:'/selectSeats',39 // name:'selectSeats',40 component:selectSeats41 },42 {43 path:'/updateClass',44 // name:'updateClass',45 component:updateClass46 },47 {48 path:'/updateStudent',49 // name:'updateStudent',50 component:updateStudent51 },52 {53 path:'/viewStudent',54 // name:'viewStudent',55 component:viewStudent56 },57 {58 path:'/changePassword',59 // name:'changePassword',60 component:changePassword61 },62 {63 path:'/admin',64 component:admin65 },66 {67 path:'/feedBackMessage',68 component:feedBackMessage69 }70 ]...
Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.updateClass('selector', 'class1', 'class2');6 await browser.close();7})();8const puppeteer = require('puppeteer');9(async () => {10 const browser = await puppeteer.launch();11 const page = await browser.newPage();12 await page.updateClass('selector', 'class1', 'class2');13 await browser.close();14})();15const webdriverio = require('webdriverio');16(async () => {17 const browser = await webdriverio.remote({18 capabilities: {19 }20 });21 await browser.updateClass('selector', 'class1', 'class2');22 await browser.deleteSession();23})();24import { Selector } from 'testcafe';25test('My first test', async t => {26 await t.updateClass('selector', 'class1', 'class2');27});28module.exports = {29 'Demo test Google' : function (browser) {30 .updateClass('selector', 'class1', 'class2')31 .end();32 }33};34const { browser } = require("protractor");35describe('Protractor Demo App', function() {36 it('should have a title', async function() {37 await browser.updateClass('selector', 'class1', 'class2');38 });39});40describe('My First Test', function() {41 it('Does not do much!', function() {42 cy.updateClass('selector', 'class1', '
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!