<commit_before>import {expectSaga} from 'redux-saga-test-plan'
import * as matchers from 'redux-saga-test-plan/matchers'
import {select, takeEvery, takeLatest, all} from 'redux-saga/effects'
import {rest} from 'tocco-app-extensions'

import * as actions from './actions'
import rootSaga, * as sagas from './sagas'

describe('input-edit', () => {
  describe('input-edit-table', () => {
    describe('sagas', () => {
      test('should fork child sagas', () => {
        const generator = rootSaga()
        expect(generator.next().value).to.deep.equal(all([
          takeLatest(actions.INITIALIZE_TABLE, sagas.initialize),
          takeLatest(actions.LOAD_DATA, sagas.loadData),
          takeEvery(actions.UPDATE_VALUE, sagas.updateValue),
          takeLatest(actions.SET_SORTING, sagas.sortData)
        ]))
        expect(generator.next().done).to.be.true
      })

      describe('initialize', () => {
        test('should load forms', () => {
          const expectedEditForm = [{
            editform: 'editform'
          }]
          const expectedDataForm = {
            dataform: 'dataform'
          }
          return expectSaga(sagas.initialize, actions.initializeTable())
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: expectedEditForm
              }],
              [matchers.call.fn(rest.fetchForm), expectedDataForm],
              [matchers.call.fn(sagas.loadData)]
            ])
            .put(actions.setEditForm({inputEditForm: expectedEditForm}))
            .put(actions.setDataForm({inputDataForm: expectedDataForm}))
            .call(sagas.loadData)
            .run()
        })
      })

      describe('load-data', () => {
        test('should load data', () => {
          const expectedData = {
            1: {
              pk: 123
            }
          }
          const expectedSorting = {
            field: 'field',
            direction: 'asc'
          }
          return expectSaga(sagas.loadData, expectedSorting)
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [select(sagas.inputEditTableSelector), {sorting: {field: 'state sorting'}}],
              [matchers.call.fn(rest.requestSaga), {
                body: expectedData
              }]
            ])
            .call(rest.requestSaga, 'inputEdit/12/data/search', {
              method: 'POST',
              body: {
                sorting: expectedSorting
              }
            })
            .put(actions.setData({data: expectedData}))
            .run()
        })
        test('should use sorting from state if none is passed', () => {
          const expectedSorting = {
            field: 'field',
            direction: 'asc'
          }
          return expectSaga(sagas.loadData)
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [select(sagas.inputEditTableSelector), {sorting: expectedSorting}],
              [matchers.call.fn(rest.requestSaga), {body: {}}]
            ])
            .call(rest.requestSaga, 'inputEdit/12/data/search', {
              method: 'POST',
              body: {
                sorting: expectedSorting
              }
            })
            .run()
        })
      })

      describe('sort-data', () => {
        test('should pass sorting to loadData', () => {
          return expectSaga(sagas.sortData, actions.setSorting('field', 'desc'))
            .provide([
              [matchers.call.fn(sagas.loadData)]
            ])
            .call(sagas.loadData, {
              field: 'field',
              direction: 'desc'
            })
            .run()
        })
      })

      describe('update-value', () => {
        test('should update value', () => {
          return expectSaga(sagas.updateValue, actions.updateValue(123, 'node', 'value'))
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: {
                }
              }]
            ])
            .put(actions.setValue(123, 'node', 'value'))
            .call(rest.requestSaga, 'inputEdit/12/data', {
              method: 'POST',
              body: {
                inputDataKey: 123,
                node: 'node',
                value: 'value'
              }
            })
            .run()
        })
        test('should set newly calculated values', () => {
          return expectSaga(sagas.updateValue, actions.updateValue(123, 'node', 'value'))
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: {
                  calculatedValues: [
                    {
                      inputDataKey: 122,
                      node: 'somenode',
                      value: 123
                    },
                    {
                      inputDataKey: 124,
                      node: 'another',
                      value: 'whatever'
                    }
                  ]
                }
              }]
            ])
            .put(actions.setValue(122, 'somenode', 123))
            .put(actions.setValue(124, 'another', 'whatever'))
            .run()
        })
      })
    })
  })
})
<commit_msg>feat(input-edit): adjust tests to work with search and pagination<commit_after>import {expectSaga} from 'redux-saga-test-plan'
import * as matchers from 'redux-saga-test-plan/matchers'
import {select, takeEvery, takeLatest, all} from 'redux-saga/effects'
import {rest} from 'tocco-app-extensions'

import * as actions from './actions'
import rootSaga, * as sagas from './sagas'

describe('input-edit', () => {
  describe('input-edit-table', () => {
    describe('sagas', () => {
      test('should fork child sagas', () => {
        const generator = rootSaga()
        expect(generator.next().value).to.deep.equal(all([
          takeLatest(actions.INITIALIZE_TABLE, sagas.initialize),
          takeLatest(actions.LOAD_DATA, sagas.loadData),
          takeEvery(actions.UPDATE_VALUE, sagas.updateValue),
          takeLatest(actions.SET_SORTING, sagas.sortData)
        ]))
        expect(generator.next().done).to.be.true
      })

      describe('initialize', () => {
        test('should load forms', () => {
          const expectedEditForm = [{
            editform: 'editform'
          }]
          const expectedDataForm = {
            dataform: 'dataform'
          }
          return expectSaga(sagas.initialize)
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: expectedEditForm
              }],
              [matchers.call.fn(rest.fetchForm), expectedDataForm],
              [matchers.call.fn(sagas.loadData), {}]
            ])
            .put(actions.setEditForm({inputEditForm: expectedEditForm}))
            .put(actions.setDataForm({inputDataForm: expectedDataForm}))
            .call(sagas.loadData, {})
            .run()
        })
      })

      describe('load-data', () => {
        test('should load data', () => {
          const expectedData = {
            count: 50,
            data: [
              {
                pk: 123
              }
            ]
          }
          const expectedSorting = {
            field: 'field',
            direction: 'asc'
          }
          const expectedSearchQueries = [
            'firstname == \'something\''
          ]
          const expectedPagination = {
            offset: 25,
            recordsPerPage: 25
          }
          return expectSaga(sagas.loadData, {
            newSorting: expectedSorting,
            newSearchQueries: expectedSearchQueries,
            newPage: 2
          })
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [select(sagas.inputEditTableSelector), {sorting: {field: 'state sorting'}}],
              [select(sagas.searchQueriesSelector), []],
              [select(sagas.inputEditPaginationSelector), {
                count: 0,
                currentPage: 1,
                recordsPerPage: 25
              }],
              [matchers.call.fn(rest.requestSaga), {
                body: expectedData
              }]
            ])
            .call.like({
              fn: rest.requestSaga,
              args: [
                'inputEdit/12/data/search',
                {
                  method: 'POST',
                  body: {
                    sorting: expectedSorting,
                    searchQueries: expectedSearchQueries,
                    pagination: expectedPagination
                  }
                }
              ]
            })
            .put(actions.setData(expectedData))
            .run()
        })
        test('should load data from state if no arguments are passed', () => {
          const expectedSorting = {
            field: 'field',
            direction: 'asc'
          }
          const expectedSearchQueries = [
            'firstname == \'whatever\''
          ]
          const expectedPagination = {
            offset: 0,
            recordsPerPage: 25
          }
          return expectSaga(sagas.loadData, {})
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [select(sagas.inputEditTableSelector), {sorting: expectedSorting}],
              [select(sagas.searchQueriesSelector), expectedSearchQueries],
              [select(sagas.inputEditPaginationSelector), {
                count: 0,
                currentPage: 1,
                recordsPerPage: 25
              }],
              [matchers.call.fn(rest.requestSaga), {body: {}}]
            ])
            .call.like({
              fn: rest.requestSaga,
              args: [
                'inputEdit/12/data/search',
                {
                  method: 'POST',
                  body: {
                    sorting: expectedSorting,
                    searchQueries: expectedSearchQueries,
                    pagination: expectedPagination
                  }
                }
              ]
            })
            .run()
        })
      })

      describe('sort-data', () => {
        test('should pass sorting to loadData', () => {
          return expectSaga(sagas.sortData, actions.setSorting('field', 'desc'))
            .provide([
              [matchers.call.fn(sagas.loadData)]
            ])
            .call(sagas.loadData, {
              newSorting: {
                field: 'field',
                direction: 'desc'
              }
            })
            .run()
        })
      })

      describe('update-value', () => {
        test('should update value', () => {
          return expectSaga(sagas.updateValue, actions.updateValue(123, 'node', 'value'))
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: {
                }
              }]
            ])
            .put(actions.setValue(123, 'node', 'value'))
            .call(rest.requestSaga, 'inputEdit/12/data', {
              method: 'POST',
              body: {
                inputDataKey: 123,
                node: 'node',
                value: 'value'
              }
            })
            .run()
        })
        test('should set newly calculated values', () => {
          return expectSaga(sagas.updateValue, actions.updateValue(123, 'node', 'value'))
            .provide([
              [select(sagas.inputSelector), {inputEntityKey: 12}],
              [matchers.call.fn(rest.requestSaga), {
                body: {
                  calculatedValues: [
                    {
                      inputDataKey: 122,
                      node: 'somenode',
                      value: 123
                    },
                    {
                      inputDataKey: 124,
                      node: 'another',
                      value: 'whatever'
                    }
                  ]
                }
              }]
            ])
            .put(actions.setValue(122, 'somenode', 123))
            .put(actions.setValue(124, 'another', 'whatever'))
            .run()
        })
      })
    })
  })
})
<|endoftext|>


<commit_before>var x = require('casper').selectXPath;
casper.options.viewportSize = {width: 1855, height: 968};
casper.on('page.error', function(msg, trace) {
   this.echo('Error: ' + msg, 'ERROR');
   for(var i=0; i<trace.length; i++) {
       var step = trace[i];
       this.echo('   ' + step.file + ' (line ' + step.line + ')', 'ERROR');
   }
});
casper.test.begin('Positive test base', function(test) {
   casper.start('http://demo.lagrummet.se/');
   casper.waitForSelector("article h1",
       function success() {
           test.assertExists("article h1");
           this.click("article h1");
       },
       function fail() {
           test.assertExists("article h1");
   });
   casper.waitForSelector(x("//*[contains(text(), \'TESTVERSION\')]"),
       function success() {
           test.assertExists(x("//*[contains(text(), \'TESTVERSION\')]"));
         },
       function fail() {
           test.assertExists(x("//*[contains(text(), \'TESTVERSION\')]"));
   });

   casper.run(function() {test.done();});
});<commit_msg>More meaningful test. #100<commit_after>var x = require('casper').selectXPath;
casper.options.viewportSize = {width: 1855, height: 968};
casper.on('page.error', function(msg, trace) {
   this.echo('Error: ' + msg, 'ERROR');
   for(var i=0; i<trace.length; i++) {
       var step = trace[i];
       this.echo('   ' + step.file + ' (line ' + step.line + ')', 'ERROR');
   }
});
casper.test.begin('Positive test base', function(test) {
   casper.start('http://admin.regression.lagrummet.se/');
   casper.waitForSelector("title",
       function success() {
           test.assertExists("title");
           this.click("title");
       },
       function fail() {
           test.assertExists("title");
   });
   casper.waitForSelector(x("//*[contains(text(), \'Index\')]"),
       function success() {
           test.assertExists(x("//*[contains(text(), \'Index\')]"));
         },
       function fail() {
           test.assertExists(x("//*[contains(text(), \'Index\')]"));
   });

   casper.run(function() {test.done();});
});<|endoftext|>


<commit_before>if (window.rcmail) {
  rcmail.addEventListener('init', function() {
	// remove the user/password/... input from login
    $('form > table > tbody > tr').each(function(){
    	$(this).remove();
    });

    // change task & action
    $('form').attr('action', './');
    $('input[name=_task]').attr('value', 'mail');
    $('input[name=_action]').attr('value', '');

	//determine twofactor field type based on config settings
	if(rcmail.env.twofactor_formfield_as_password)
		var twoFactorCodeFieldType = 'password';
	else
		var twoFactorCodeFieldType = 'text';

	//twofactor input form
    var text = '';
    text += '
';
    text += ''+rcmail.gettext('two_step_verification_form', 'twofactor_gauthenticator')+'	';
    text += '<input name="_code_2FA" id="2FA_code" size="10" autocapitalize="off" autocomplete="off" type="' + twoFactorCodeFieldType + '" maxlength="10">	';
    text += '
';

    // remember option
    if(rcmail.env.allow_save_device_30days){
		text += '
';
		text += '<input type="checkbox" id="remember_2FA" name="_remember_2FA" value="yes"/>'+rcmail.gettext('dont_ask_me_30days', 'twofactor_gauthenticator')+'	';
		text += '
';
	}

    // create textbox
    $('form > table > tbody:last').append(text);

    // focus
    $('#2FA_code').focus();

  });

};
<commit_msg>changed class from remember text<commit_after>if (window.rcmail) {
  rcmail.addEventListener('init', function() {
	// remove the user/password/... input from login
    $('form > table > tbody > tr').each(function(){
    	$(this).remove();
    });

    // change task & action
    $('form').attr('action', './');
    $('input[name=_task]').attr('value', 'mail');
    $('input[name=_action]').attr('value', '');

	//determine twofactor field type based on config settings
	if(rcmail.env.twofactor_formfield_as_password)
		var twoFactorCodeFieldType = 'password';
	else
		var twoFactorCodeFieldType = 'text';

	//twofactor input form
    var text = '';
    text += '
';
    text += ''+rcmail.gettext('two_step_verification_form', 'twofactor_gauthenticator')+'	';
    text += '<input name="_code_2FA" id="2FA_code" size="10" autocapitalize="off" autocomplete="off" type="' + twoFactorCodeFieldType + '" maxlength="10">	';
    text += '
';

    // remember option
    if(rcmail.env.allow_save_device_30days){
		text += '
';
		text += '<input type="checkbox" id="remember_2FA" name="_remember_2FA" value="yes"/>'+rcmail.gettext('dont_ask_me_30days', 'twofactor_gauthenticator')+'	';
		text += '
';
	}

    // create textbox
    $('form > table > tbody:last').append(text);

    // focus
    $('#2FA_code').focus();

  });

};
<|endoftext|>


<commit_before>Resource.inject({
	statics: {
		/**
		 * Returns any of these, based on the content type:
		 * image, audio, video, code, director, flash, pdf, text
		 */
		getBasicType: function(mimeType) {
			if (/^image/.test(mimeType))
				return 'image';
			else if (/^video/.test(mimeType))
			 	return 'video';
			else if (/^audio/.test(mimeType))
				return 'audio';
			else if (mimeType == 'application/x-shockwave-flash')
				return 'flash';
			else if (mimeType == 'application/x-director')
				return 'director';
			else if (mimeType == 'application/x-javascript')
				return 'code';
			else if (mimeType == 'application/pdf')
				return 'pdf';
			else if (/^application\/(zip|x-(stuffit|gtar|tar|gzip))$/.test(mimeType))
				return 'archive';
			else
				return 'text';
		},

		create: function(mimeObj) {
			if (mimeObj && mimeObj.name) {
				var type = Resource.getBasicType(File.getContentType(mimeObj.name));
				if (type) {
					switch (type) {
						case 'image':
							var picture = new Picture(mimeObj);
							if (picture.isValid()) return picture;
							else picture.remove();
							break;
						case 'video':
						case 'audio':
						case 'flash':
						case 'director':
							return new Medium(mimeObj);
						default:
							return new Resource(mimeObj);
					}
				}
			}
			return null;
		}
	},

	initialize: function(mimeObj) {
		if (mimeObj && mimeObj.name)
			this.setFile(mimeObj);
		this.counter = 0;
	},

	getEditForm: function(param) {
		var form = new EditForm(this, {
			removable: true, width: param.width
		});
		if (param.name === undefined)
			param.name = false;
		if (param.file === undefined)
			param.file = true;
		// Allow sub-prototypes to display a name field easily through param
		form.add(
			form.createItem(param.name, {
				name: 'name', type: 'string', label: 'Name',
				length: 64
			}),
			form.createItem(param.file, {
				name: 'file', type: 'file', label: 'File',
				onApply: this.setFile,
				preview: this.name && this.renderIcon({
					small: true, details: true
				})
			})
		);
		return form;
	},

	onCreate: function() {
		this.visible = 1;
	},

	onRemove: function() {
		this.removeResource();
	},

	onStore: function(transId) {
		// When the resources is stored, rename the file
		// from transient to persistend id
		if (transId) {
			var file = this.getFile(transId);
			if (file.exists())
				file.renameTo(this.getFile())
		}
	},

	setFile: function(mimeObj) {
		var ext = mimeObj && File.getExtension(mimeObj.name);
		if (ext) {
			ext = ext.toLowerCase();
			// remove old file:
			this.removeResource();
			this.name = mimeObj.name;
			this.extension = ext;
			var file = this.getFile();
			mimeObj.writeToFile(file.getParent(), file.getName());
			// Every time the file is changed, it can increase a verion field in the database.
			// This can be used to force refresh of caches.
			// But only do this if the field is actually defined.
			if (this.version !== undefined) {
				if (this.version == null) this.version = 0;
				else this.version++;
			}
			return true;
		}
		return false;
	},

	getFilename: function(id) {
		return  (id != null ? id : this._id) + '.' + this.extension;
	},

	getFile: function(id) {
		return new File(app.properties.resourceDir, this.getFilename(id));
	},

	/**
	 * Returns the href without the trailing /, so a differenciation can be
	 * made between requestion the resource (without /) and the html code to
	 * display it (with /).
	 */
	getUri: function() {
		var href = this.href();
		if (href)
			return href.substring(0, href.length - 1);
	},

	/**
	 * Renders the link for a link to the resource.
	 */
	renderLink: function(param, out) {
		// Convert to object param first:
		if (!param || typeof param == 'string')
			param = { content: param };
		// Override default href (this.href())
		if (!param.href && !param.object) {
			// Open in blank window if it's not forcing a download
			if (!this.forceDownload()) {
				if (!param.attributes)
					param.attributes = {};
				param.attributes.target = '_blank';
			}
		}
		return this.base(param, out);
	},

	getVersionFile: function(versionId, extension) {
		return new File(app.properties.resourceDir, 'versions/' + this._id +
			(versionId ? '_' + versionId : '') + '.' + (extension || this.extension));
	},

	removeVersionFiles: function() {
		if (this.extension) {
			// Remove all thumbnails of this image through java.io.File filtering
			var versions = new File(app.properties.resourceDir, 'versions').list(
					new RegExp('^' + this._id + '[_.]'));
			for each (file in versions) {
				User.log('Removing ' + file);
				file.remove();
			}
		}
	},

	removeResource: function() {
		if (this.extension) {
			this.getFile().remove();
			this.removeVersionFiles();
			this.extension = null;

		}
	},

	/**
	 * By default, anything that is not image, video or audio needs to be downloaded
	 * This can be overridden by any application
	 */
	forceDownload: function() {
		return !/^(image|movie|audio)/.test(this.getContentType());
	},

	forwardFile: function(file) {
		if (!file)
			file = this.getFile();
		if (file.exists()) {
			res.contentType = file.getContentType();
			if (req.data.download || this.forceDownload()) {
				this.counter++;
				res.servletResponse.setHeader('Content-Disposition',
						'attachment; filename="' + this.name + '"');
			}
			// res.forward takes the filename relative to the protectedStatic, so resolve here.
			res.forward(file.getRelativePath(app.properties.protectedDir));
		} else {
			app.log('ERROR: Requesting inexisting file: ' + file);
		}
	},

	getContentType: function() {
		return File.getContentType(this.extension);
	},

	renderIcon: function(param, out) {
		if (!param.name)
			param.name = encode(this.name);
		param.src = app.properties.iconUri + this.getIcon(param.small);
		if (param.details)
			param.details = ' (' +
				// Display image / video size for media
				(this instanceof Medium ? this.width + ' x ' + this.height + ' Pixels, ' : '') +
				// File size
				this.getFile().getSizeAsString() +
				')';
		param.width = param.height = param.small ? 16 : 32;
		return this.renderTemplate('icon', param, out);
	},

	/**
	 * Returns any of these, based on the content type:
	 * image, audio, video, code, director, flash, text
	 */
	getBasicType: function() {
		return Resource.getBasicType(this.getContentType());
	},

	getIcon: function(small) {
		var icon = this.getBasicType();
		if (small) icon += '_small';
		return icon + '.gif';
	}
});
<commit_msg>Added Resource#hasFile.<commit_after>Resource.inject({
	statics: {
		/**
		 * Returns any of these, based on the content type:
		 * image, audio, video, code, director, flash, pdf, text
		 */
		getBasicType: function(mimeType) {
			if (/^image/.test(mimeType))
				return 'image';
			else if (/^video/.test(mimeType))
			 	return 'video';
			else if (/^audio/.test(mimeType))
				return 'audio';
			else if (mimeType == 'application/x-shockwave-flash')
				return 'flash';
			else if (mimeType == 'application/x-director')
				return 'director';
			else if (mimeType == 'application/x-javascript')
				return 'code';
			else if (mimeType == 'application/pdf')
				return 'pdf';
			else if (/^application\/(zip|x-(stuffit|gtar|tar|gzip))$/.test(mimeType))
				return 'archive';
			else
				return 'text';
		},

		create: function(mimeObj) {
			if (mimeObj && mimeObj.name) {
				var type = Resource.getBasicType(File.getContentType(mimeObj.name));
				if (type) {
					switch (type) {
						case 'image':
							var picture = new Picture(mimeObj);
							if (picture.isValid()) return picture;
							else picture.remove();
							break;
						case 'video':
						case 'audio':
						case 'flash':
						case 'director':
							return new Medium(mimeObj);
						default:
							return new Resource(mimeObj);
					}
				}
			}
			return null;
		}
	},

	initialize: function(mimeObj) {
		if (mimeObj && mimeObj.name)
			this.setFile(mimeObj);
		this.counter = 0;
	},

	getEditForm: function(param) {
		var form = new EditForm(this, {
			removable: true, width: param.width
		});
		if (param.name === undefined)
			param.name = false;
		if (param.file === undefined)
			param.file = true;
		// Allow sub-prototypes to display a name field easily through param
		form.add(
			form.createItem(param.name, {
				name: 'name', type: 'string', label: 'Name',
				length: 64
			}),
			form.createItem(param.file, {
				name: 'file', type: 'file', label: 'File',
				onApply: this.setFile,
				preview: this.name && this.renderIcon({
					small: true, details: true
				})
			})
		);
		return form;
	},

	onCreate: function() {
		this.visible = 1;
	},

	onRemove: function() {
		this.removeResource();
	},

	onStore: function(transId) {
		// When the resources is stored, rename the file
		// from transient to persistend id
		if (transId) {
			var file = this.getFile(transId);
			if (file.exists())
				file.renameTo(this.getFile())
		}
	},

	setFile: function(mimeObj) {
		var ext = mimeObj && File.getExtension(mimeObj.name);
		if (ext) {
			ext = ext.toLowerCase();
			// remove old file:
			this.removeResource();
			this.name = mimeObj.name;
			this.extension = ext;
			var file = this.getFile();
			mimeObj.writeToFile(file.getParent(), file.getName());
			// Every time the file is changed, it can increase a verion field in the database.
			// This can be used to force refresh of caches.
			// But only do this if the field is actually defined.
			if (this.version !== undefined) {
				if (this.version == null) this.version = 0;
				else this.version++;
			}
			return true;
		}
		return false;
	},

	getFilename: function(id) {
		return  (id != null ? id : this._id) + '.' + this.extension;
	},

	getFile: function(id) {
		return new File(app.properties.resourceDir, this.getFilename(id));
	},

	hasFile: function() {
		return !!this.extension;
	},

	/**
	 * Returns the href without the trailing /, so a differenciation can be
	 * made between requestion the resource (without /) and the html code to
	 * display it (with /).
	 */
	getUri: function() {
		var href = this.href();
		if (href)
			return href.substring(0, href.length - 1);
	},

	/**
	 * Renders the link for a link to the resource.
	 */
	renderLink: function(param, out) {
		// Convert to object param first:
		if (!param || typeof param == 'string')
			param = { content: param };
		// Override default href (this.href())
		if (!param.href && !param.object) {
			// Open in blank window if it's not forcing a download
			if (!this.forceDownload()) {
				if (!param.attributes)
					param.attributes = {};
				param.attributes.target = '_blank';
			}
		}
		return this.base(param, out);
	},

	getVersionFile: function(versionId, extension) {
		return new File(app.properties.resourceDir, 'versions/' + this._id +
			(versionId ? '_' + versionId : '') + '.' + (extension || this.extension));
	},

	removeVersionFiles: function() {
		if (this.extension) {
			// Remove all thumbnails of this image through java.io.File filtering
			var versions = new File(app.properties.resourceDir, 'versions').list(
					new RegExp('^' + this._id + '[_.]'));
			for each (file in versions) {
				User.log('Removing ' + file);
				file.remove();
			}
		}
	},

	removeResource: function() {
		if (this.extension) {
			this.getFile().remove();
			this.removeVersionFiles();
			this.extension = null;

		}
	},

	/**
	 * By default, anything that is not image, video or audio needs to be downloaded
	 * This can be overridden by any application
	 */
	forceDownload: function() {
		return !/^(image|movie|audio)/.test(this.getContentType());
	},

	forwardFile: function(file) {
		if (!file)
			file = this.getFile();
		if (file.exists()) {
			res.contentType = file.getContentType();
			if (req.data.download || this.forceDownload()) {
				this.counter++;
				res.servletResponse.setHeader('Content-Disposition',
						'attachment; filename="' + this.name + '"');
			}
			// res.forward takes the filename relative to the protectedStatic, so resolve here.
			res.forward(file.getRelativePath(app.properties.protectedDir));
		} else {
			app.log('ERROR: Requesting inexisting file: ' + file);
		}
	},

	getContentType: function() {
		return File.getContentType(this.extension);
	},

	renderIcon: function(param, out) {
		if (!param.name)
			param.name = encode(this.name);
		param.src = app.properties.iconUri + this.getIcon(param.small);
		if (param.details)
			param.details = ' (' +
				// Display image / video size for media
				(this instanceof Medium ? this.width + ' x ' + this.height + ' Pixels, ' : '') +
				// File size
				this.getFile().getSizeAsString() +
				')';
		param.width = param.height = param.small ? 16 : 32;
		return this.renderTemplate('icon', param, out);
	},

	/**
	 * Returns any of these, based on the content type:
	 * image, audio, video, code, director, flash, text
	 */
	getBasicType: function() {
		return Resource.getBasicType(this.getContentType());
	},

	getIcon: function(small) {
		var icon = this.getBasicType();
		if (small) icon += '_small';
		return icon + '.gif';
	}
});
<|endoftext|>


<commit_before>/* eslint-disable no-console */

// In production, we register a service worker to serve assets from local cache.

// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.

// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

export default function register() {
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
      return;
    }

    window.addEventListener('load', () => {
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

      if (isLocalhost) {
        // This is running on localhost. Lets check if a service worker still exists or not.
        checkValidServiceWorker(swUrl);

        // Add some additional logging to localhost, pointing developers to the
        // service worker/PWA documentation.
        navigator.serviceWorker.ready.then(() => {
          console.log(
            'This web app is being served cache-first by a service ' +
              'worker. To learn more, visit https://goo.gl/SC7cgQ'
          );
        });
      } else {
        // Is not local host. Just register service worker
        registerValidSW(swUrl);
      }
    });
  }
}

function registerValidSW(swUrl) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        installingWorker.onstatechange = () => {
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              // At this point, the old content will have been purged and
              // the fresh content will have been added to the cache.
              // It's the perfect time to display a "New content is
              // available; please refresh." message in your web app.
              console.log('New content is available; please refresh.');
            } else {
              // At this point, everything has been precached.
              // It's the perfect time to display a
              // "Content is cached for offline use." message.
              console.log('Content is cached for offline use.');
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}

function checkValidServiceWorker(swUrl) {
  // Check if the service worker can be found. If it can't reload the page.
  fetch(swUrl)
    .then(response => {
      // Ensure service worker exists, and that we really are getting a JS file.
      if (
        response.status === 404 ||
        response.headers.get('content-type').indexOf('javascript') === -1
      ) {
        // No service worker found. Probably a different app. Reload the page.
        navigator.serviceWorker.ready.then(registration => {
          registration.unregister().then(() => {
            window.location.reload();
          });
        });
      } else {
        // Service worker found. Proceed as normal.
        registerValidSW(swUrl);
      }
    })
    .catch(() => {
      console.log(
        'No internet connection found. App is running in offline mode.'
      );
    });
}

export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
      registration.unregister();
    });
  }
}
<commit_msg>Remove unnecessary eslint-disable<commit_after>// In production, we register a service worker to serve assets from local cache.

// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.

// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

export default function register() {
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
      return;
    }

    window.addEventListener('load', () => {
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

      if (isLocalhost) {
        // This is running on localhost. Lets check if a service worker still exists or not.
        checkValidServiceWorker(swUrl);

        // Add some additional logging to localhost, pointing developers to the
        // service worker/PWA documentation.
        navigator.serviceWorker.ready.then(() => {
          console.log(
            'This web app is being served cache-first by a service ' +
              'worker. To learn more, visit https://goo.gl/SC7cgQ'
          );
        });
      } else {
        // Is not local host. Just register service worker
        registerValidSW(swUrl);
      }
    });
  }
}

function registerValidSW(swUrl) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        installingWorker.onstatechange = () => {
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              // At this point, the old content will have been purged and
              // the fresh content will have been added to the cache.
              // It's the perfect time to display a "New content is
              // available; please refresh." message in your web app.
              console.log('New content is available; please refresh.');
            } else {
              // At this point, everything has been precached.
              // It's the perfect time to display a
              // "Content is cached for offline use." message.
              console.log('Content is cached for offline use.');
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}

function checkValidServiceWorker(swUrl) {
  // Check if the service worker can be found. If it can't reload the page.
  fetch(swUrl)
    .then(response => {
      // Ensure service worker exists, and that we really are getting a JS file.
      if (
        response.status === 404 ||
        response.headers.get('content-type').indexOf('javascript') === -1
      ) {
        // No service worker found. Probably a different app. Reload the page.
        navigator.serviceWorker.ready.then(registration => {
          registration.unregister().then(() => {
            window.location.reload();
          });
        });
      } else {
        // Service worker found. Proceed as normal.
        registerValidSW(swUrl);
      }
    })
    .catch(() => {
      console.log(
        'No internet connection found. App is running in offline mode.'
      );
    });
}

export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
      registration.unregister();
    });
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import invariant from 'shared/invariant';

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persistent';

export const debugRenderPhaseSideEffects = false;
export const debugRenderPhaseSideEffectsForStrictMode = false;
export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = false;
export const enableSchedulerTracing = false;
export const enableSuspenseServerRenderer = false;
export const enableStableConcurrentModeAPIs = false;
export const enableSchedulerDebugging = false;
export const warnAboutDeprecatedSetNativeProps = false;
export const disableJavaScriptURLs = false;
export const disableYielding = false;
export const enableEventAPI = true;
export const enableJSXTransformAPI = true;
export const revertPassiveEffectsChange = false;

// Only used in www builds.
export function addUserTimingListener() {
  invariant(false, 'Not implemented.');
}

// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;
// eslint-disable-next-line no-unused-expressions
(null: Check<PersistentFeatureFlagsType, FeatureFlagsType>);
<commit_msg>Use dynamic flag in test renderer in www (#15662)<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import invariant from 'shared/invariant';

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persistent';

// Re-export dynamic flags from the www version.
export const {revertPassiveEffectsChange} = require('ReactFeatureFlags');

export const debugRenderPhaseSideEffects = false;
export const debugRenderPhaseSideEffectsForStrictMode = false;
export const enableUserTimingAPI = __DEV__;
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const enableProfilerTimer = false;
export const enableSchedulerTracing = false;
export const enableSuspenseServerRenderer = false;
export const enableStableConcurrentModeAPIs = false;
export const enableSchedulerDebugging = false;
export const warnAboutDeprecatedSetNativeProps = false;
export const disableJavaScriptURLs = false;
export const disableYielding = false;
export const enableEventAPI = true;
export const enableJSXTransformAPI = true;

// Only used in www builds.
export function addUserTimingListener() {
  invariant(false, 'Not implemented.');
}

// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;
// eslint-disable-next-line no-unused-expressions
(null: Check<PersistentFeatureFlagsType, FeatureFlagsType>);
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import _isEmpty from 'lodash/isEmpty'
import _get from 'lodash/get'

import Link from '../../Link'
import {
  StyledEditableControl,
  StyledEditableWrapper
} from '../StyledEditableValue'
import StyledPhoneEdit from './StyledPhoneEdit'

class PhoneEdit extends React.Component {
  componentIsUnmounted = false
  FALLBACK_DEFAULT_COUNTRY = 'CH'

  constructor(props) {
    super(props)
    const defaultCountry = _get(props, 'options.defaultCountry') || this.FALLBACK_DEFAULT_COUNTRY
    this.state = {libPhoneImport: null, defaultCountry}
    this.importLibPhoneNumber()
    this.inputElement = React.createRef()
  }

  async importLibPhoneNumber() {
    const libPhoneImport = await import(/* webpackChunkName: "libphonenumber-js" */ 'libphonenumber-js')
    if (!this.componentIsUnmounted) {
      this.setState({...this.state, libPhoneImport})
    }
  }

  componentWillUnmount() {
    this.componentIsUnmounted = true
  }

  amountOfSpacesBeforeCaret = (str, caretPosition) => {
    const spaces = str.substring(0, caretPosition - 1).match(/\s/g)
    return spaces ? spaces.length : 0
  }

  repositionCaret = (value, previousValue, caretPosition) => {
    if (caretPosition && value.length !== caretPosition) {
      const previousFormatted = new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(previousValue)
      const currentFormatted = new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(value)

      const spacesPrevious = this.amountOfSpacesBeforeCaret(previousFormatted, caretPosition)
      const spacesCurrent = this.amountOfSpacesBeforeCaret(currentFormatted, caretPosition)

      const offset = spacesCurrent - spacesPrevious

      window.requestAnimationFrame(function() {
        const start = caretPosition + offset
        this.setSelectionRange(start, start)
      }.bind(this.inputElement.current))
    }
  }

  removeSpaces = str => str.replace(/\s/g, '')

  handleChange = e => {
    const newValue = e.target.value
    const {libPhoneImport} = this.state
    const parsedNumber = libPhoneImport ? libPhoneImport.parseNumber(newValue, this.state.defaultCountry) : newValue

    const valueNormalized = _isEmpty(parsedNumber)
      ? this.removeSpaces(new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(newValue))
      : libPhoneImport.formatNumber(parsedNumber, 'E.164')

    this.props.onChange(valueNormalized)

    const currentCaretPosition = e.target.selectionStart
    this.repositionCaret(newValue, this.props.value, currentCaretPosition)
  }

  determineDisplayValue = () => {
    if (this.state.libPhoneImport && this.state.libPhoneImport.AsYouType) {
      return new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(this.props.value)
    }

    return this.props.value || ''
  }

  render() {
    const displayValue = this.determineDisplayValue()

    return (
      <StyledEditableWrapper immutable={this.props.immutable}>
        <StyledPhoneEdit
          disabled={this.props.immutable || !this.state.libPhoneImport}
          id={this.props.id}
          name={name}
          onChange={this.handleChange}
          immutable={this.props.immutable || !this.state.libPhoneImport}
          ref={this.inputElement}
          value={displayValue}
        />
        {displayValue && <StyledEditableControl>
          <Link
            href={`tel:${this.props.value}`}
            icon="phone"
            tabIndex={-1}
            neutral
          />
        </StyledEditableControl>}
      </StyledEditableWrapper>
    )
  }
}

PhoneEdit.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.node,
  name: PropTypes.string,
  id: PropTypes.string,
  immutable: PropTypes.bool,
  options: PropTypes.shape({
    defaultCountry: PropTypes.string,
    customPhoneRegex: PropTypes.string
  })
}

export default PhoneEdit
<commit_msg>fix(tocco-ui): only format number if defined<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import _isEmpty from 'lodash/isEmpty'
import _get from 'lodash/get'

import Link from '../../Link'
import {
  StyledEditableControl,
  StyledEditableWrapper
} from '../StyledEditableValue'
import StyledPhoneEdit from './StyledPhoneEdit'

class PhoneEdit extends React.Component {
  componentIsUnmounted = false
  FALLBACK_DEFAULT_COUNTRY = 'CH'

  constructor(props) {
    super(props)
    const defaultCountry = _get(props, 'options.defaultCountry') || this.FALLBACK_DEFAULT_COUNTRY
    this.state = {libPhoneImport: null, defaultCountry}
    this.importLibPhoneNumber()
    this.inputElement = React.createRef()
  }

  async importLibPhoneNumber() {
    const libPhoneImport = await import(/* webpackChunkName: "libphonenumber-js" */ 'libphonenumber-js')
    if (!this.componentIsUnmounted) {
      this.setState({...this.state, libPhoneImport})
    }
  }

  componentWillUnmount() {
    this.componentIsUnmounted = true
  }

  amountOfSpacesBeforeCaret = (str, caretPosition) => {
    const spaces = str.substring(0, caretPosition - 1).match(/\s/g)
    return spaces ? spaces.length : 0
  }

  repositionCaret = (value, previousValue, caretPosition) => {
    if (caretPosition && value.length !== caretPosition) {
      const previousFormatted = new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(previousValue)
      const currentFormatted = new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(value)

      const spacesPrevious = this.amountOfSpacesBeforeCaret(previousFormatted, caretPosition)
      const spacesCurrent = this.amountOfSpacesBeforeCaret(currentFormatted, caretPosition)

      const offset = spacesCurrent - spacesPrevious

      window.requestAnimationFrame(function() {
        const start = caretPosition + offset
        this.setSelectionRange(start, start)
      }.bind(this.inputElement.current))
    }
  }

  removeSpaces = str => str.replace(/\s/g, '')

  handleChange = e => {
    const newValue = e.target.value
    const {libPhoneImport} = this.state
    const parsedNumber = libPhoneImport ? libPhoneImport.parseNumber(newValue, this.state.defaultCountry) : newValue

    const valueNormalized = _isEmpty(parsedNumber)
      ? this.removeSpaces(new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(newValue))
      : libPhoneImport.formatNumber(parsedNumber, 'E.164')

    this.props.onChange(valueNormalized)

    const currentCaretPosition = e.target.selectionStart
    this.repositionCaret(newValue, this.props.value, currentCaretPosition)
  }

  determineDisplayValue = () => {
    if (this.props.value && this.state.libPhoneImport && this.state.libPhoneImport.AsYouType) {
      return new this.state.libPhoneImport.AsYouType(this.state.defaultCountry).input(this.props.value)
    }

    return this.props.value || ''
  }

  render() {
    const displayValue = this.determineDisplayValue()

    return (
      <StyledEditableWrapper immutable={this.props.immutable}>
        <StyledPhoneEdit
          disabled={this.props.immutable || !this.state.libPhoneImport}
          id={this.props.id}
          name={name}
          onChange={this.handleChange}
          immutable={this.props.immutable || !this.state.libPhoneImport}
          ref={this.inputElement}
          value={displayValue}
        />
        {displayValue && <StyledEditableControl>
          <Link
            href={`tel:${this.props.value}`}
            icon="phone"
            tabIndex={-1}
            neutral
          />
        </StyledEditableControl>}
      </StyledEditableWrapper>
    )
  }
}

PhoneEdit.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.node,
  name: PropTypes.string,
  id: PropTypes.string,
  immutable: PropTypes.bool,
  options: PropTypes.shape({
    defaultCountry: PropTypes.string,
    customPhoneRegex: PropTypes.string
  })
}

export default PhoneEdit
<|endoftext|>


<commit_before>import * as list from "../../util/list";
import * as async from "../../util/async";
import * as event from "../../util/event";
import * as record from "../../util/record";
import * as timer from "../../util/timer";
import { uuid_port_tab } from "../../common/uuid";
import { ports } from "../../chrome/client";
import { assert } from "../../util/assert";

const duration = timer.make();

export const init = async.make();

const port       = ports.open(uuid_port_tab);
const windows    = list.make();
const window_ids = record.make();
const tab_ids    = record.make();
const events     = event.make();

const make_window = (info) =>
  record.make({
    "id": record.get(info, "id"),
    "name": record.get(info, "name"),
    "tabs": list.make(),
  });

const make_tab = (info, transient, window) => {
  const url   = record.get(info, "url");
  const title = record.get(info, "title");

  return record.make({
    "id": record.get(info, "id"),
    "window": window,
    "time": record.make(record.get(info, "time")),

    "url": url,
    // TODO maybe this should be server-side ?
    "title": title || url,
    "favicon": record.get(info, "favicon"),
    "pinned": record.get(info, "pinned"),

    "focused": (transient !== null && record.get(transient, "focused")),
    "unloaded": (transient === null),
  });
};

const close_tabs = (a) => {
  ports.send(port, record.make({
    "type": "close-tabs",
    "tabs": list.map(a, (tab) => record.get(tab, "id"))
  }));
};

const focus_tab = (tab) => {
  ports.send(port, record.make({
    "type": "focus-tab",
    "tab-id": record.get(tab, "id")
  }));
};

const types = record.make({
  "init": (info) => {
    const _windows = record.get(info, "current.windows");
    const _window_ids = record.get(info, "current.window-ids");
    const _tab_ids = record.get(info, "current.tab-ids");
    const _transient_tab_ids = record.get(info, "transient.tab-ids");

    list.each(_windows, (id) => {
      const info = record.get(_window_ids, id);

      const window = make_window(info);

      const tabs = record.get(window, "tabs");

      list.each(record.get(info, "tabs"), (id) => {
        const info = record.get(_tab_ids, id);

        const transient = (record.has(_transient_tab_ids, id)
                            ? record.get(_transient_tab_ids, id)
                            : null);

        const tab = make_tab(info, transient, window);

        record.insert(tab_ids, record.get(tab, "id"), tab);

        list.push(tabs, tab);
      });

      record.insert(window_ids, record.get(window, "id"), window);

      list.push(windows, window);
    });

    timer.done(duration);
    console["debug"]("tabs: initialized (" + timer.diff(duration) + "ms)");

    async.success(init, { windows, events, focus_tab, close_tabs });
  },

  "tab-open": (json) => {
    const info      = record.get(json, "tab");
    const window_id = record.get(json, "window-id");
    const index     = record.get(json, "tab-index");
    const transient = record.get(json, "tab-transient");

    const window = record.get(window_ids, window_id);
    const tabs   = record.get(window, "tabs");

    const tab = make_tab(info, transient, window);

    record.insert(tab_ids, record.get(tab, "id"), tab);

    list.insert(tabs, index, tab);

    event.send(events, {
      type: "tab-open",
      window,
      tab,
      index
    });
  },

  "tab-focus": (json) => {
    const id = record.get(json, "tab-id");
    const time_focused = record.get(json, "tab-time-focused");

    const tab = record.get(tab_ids, id);

    record.update(tab, "focused", true);
    // TODO test this
    record.assign(record.get(tab, "time"), "focused", time_focused);

    event.send(events, {
      type: "tab-focus",
      tab
    });
  },

  "tab-unfocus": (json) => {
    const id = record.get(json, "tab-id");

    const tab = record.get(tab_ids, id);

    record.update(tab, "focused", false);

    event.send(events, {
      type: "tab-unfocus",
      tab
    });
  },

  "tab-update": (json) => {
    const id = record.get(json, "tab-id");
    const url = record.get(json, "tab-url");
    const title = record.get(json, "tab-title");
    const favicon = record.get(json, "tab-favicon");
    const pinned = record.get(json, "tab-pinned");
    const time = record.get(json, "tab-time-updated");

    const tab = record.get(tab_ids, id);

    // TODO code duplication
    record.update(tab, "url", url);
    // TODO maybe this should be server-side ?
    record.update(tab, "title", title || url);
    record.update(tab, "favicon", favicon);
    record.update(tab, "pinned", pinned);
    record.assign(record.get(tab, "time"), "updated", time);

    event.send(events, {
      type: "tab-update",
      tab
    });
  },

  "tab-move": (json) => {
    const old_window_id = record.get(json, "window-old-id");
    const new_window_id = record.get(json, "window-new-id");
    const old_index = record.get(json, "tab-old-index");
    const new_index = record.get(json, "tab-new-index");
    const tab_id = record.get(json, "tab-id");
    const time_moved = record.get(json, "tab-time-moved");

    const old_window = record.get(window_ids, old_window_id);
    const new_window = record.get(window_ids, new_window_id);
    const old_tabs = record.get(old_window, "tabs");
    const new_tabs = record.get(new_window, "tabs");
    const tab = record.get(tab_ids, tab_id);

    assert(record.get(tab, "window") === old_window);
    record.update(tab, "window", new_window);
    // TODO test this
    record.assign(record.get(tab, "time"), "moved", time_moved);

    assert(list.get(old_tabs, old_index) === tab);

    list.remove(old_tabs, old_index);
    list.insert(new_tabs, new_index, tab);

    event.send(events, {
      type: "tab-move",
      tab,
      old_window,
      new_window,
      old_index,
      new_index
    });
  },

  "tab-close": (json) => {
    const window_id = record.get(json, "window-id");
    const tab_id = record.get(json, "tab-id");
    const index = record.get(json, "tab-index");

    const window = record.get(window_ids, window_id);
    const tab = record.get(tab_ids, tab_id);
    const tabs = record.get(window, "tabs");

    record.update(tab, "window", null);

    record.remove(tab_ids, record.get(tab, "id"));

    assert(list.get(tabs, index) === tab);

    list.remove(tabs, index);

    event.send(events, {
      type: "tab-close",
      window,
      tab,
      index
    });
  },

  "window-open": (json) => {
    const info = record.get(json, "window");
    const index = record.get(json, "window-index");

    const window = make_window(info);

    assert(list.size(record.get(info, "tabs")) === 0);

    record.insert(window_ids, record.get(window, "id"), window);

    list.insert(windows, index, window);

    event.send(events, {
      type: "window-open",
      window,
      index
    });
  },

  "window-close": (json) => {
    const window_id = record.get(json, "window-id");
    const index = record.get(json, "window-index");

    const window = record.get(window_ids, window_id);

    assert(list.size(record.get(window, "tabs")) === 0);

    record.remove(window_ids, record.get(window, "id"));

    assert(list.get(windows, index) === window);

    list.remove(windows, index);

    event.send(events, {
      type: "window-close",
      window,
      index
    });
  }
});

ports.on_receive(port, (x) => {
  record.get(types, record.get(x, "type"))(x);
});
<commit_msg>Synchronizing current.tag-ids<commit_after>import * as list from "../../util/list";
import * as async from "../../util/async";
import * as event from "../../util/event";
import * as record from "../../util/record";
import * as timer from "../../util/timer";
import { uuid_port_tab } from "../../common/uuid";
import { ports } from "../../chrome/client";
import { assert } from "../../util/assert";

const duration = timer.make();

export const init = async.make();

const port       = ports.open(uuid_port_tab);
const windows    = list.make();
const tags       = record.make();
const window_ids = record.make();
const tab_ids    = record.make();
const events     = event.make();

const make_tag = (info, tabs) =>
  record.make({
    "id": record.get(info, "id"),
    "tabs": tabs
  });

const make_window = (info, tabs) =>
  record.make({
    "id": record.get(info, "id"),
    "name": record.get(info, "name"),
    "tabs": tabs,
  });

const make_tab = (info, transient) => {
  const url   = record.get(info, "url");
  const title = record.get(info, "title");

  return record.make({
    "id": record.get(info, "id"),
    "time": record.make(record.get(info, "time")),

    "url": url,
    // TODO maybe this should be server-side ?
    "title": title || url,
    "favicon": record.get(info, "favicon"),
    "pinned": record.get(info, "pinned"),

    "focused": (transient !== null && record.get(transient, "focused")),
    "unloaded": (transient === null),
  });
};

const close_tabs = (a) => {
  ports.send(port, record.make({
    "type": "close-tabs",
    "tabs": list.map(a, (tab) => record.get(tab, "id"))
  }));
};

const focus_tab = (tab) => {
  ports.send(port, record.make({
    "type": "focus-tab",
    "tab-id": record.get(tab, "id")
  }));
};

const types = record.make({
  "init": (info) => {
    const _windows = record.get(info, "current.windows");
    const _window_ids = record.get(info, "current.window-ids");
    const _tab_ids = record.get(info, "current.tab-ids");
    const _transient_tab_ids = record.get(info, "transient.tab-ids");
    const _tag_ids = record.get(info, "current.tag-ids");

    list.each(_windows, (id) => {
      const info = record.get(_window_ids, id);

      const tabs = record.get(info, "tabs");

      const window = make_window(info, list.map(tabs, (id) => {
        const info = record.get(_tab_ids, id);

        const transient = (record.has(_transient_tab_ids, id)
                            ? record.get(_transient_tab_ids, id)
                            : null);

        const tab = make_tab(info, transient);

        record.insert(tab_ids, record.get(tab, "id"), tab);

        return tab;
      }));

      record.insert(window_ids, record.get(window, "id"), window);

      list.push(windows, window);
    });

    record.each(_tag_ids, (id, info) => {
      const tabs = record.get(info, "tabs");

      const tag = make_tag(info, list.map(tabs, (id) =>
                                   record.get(tab_ids, id)));

      record.insert(tags, record.get(tag, "id"), tag);
    });

    timer.done(duration);
    console["debug"]("tabs: initialized (" + timer.diff(duration) + "ms)");

    async.success(init, { windows, tags, events, focus_tab, close_tabs });
  },

  "tab-open": (json) => {
    const info      = record.get(json, "tab");
    const window_id = record.get(json, "window-id");
    const index     = record.get(json, "tab-index");
    const transient = record.get(json, "tab-transient");

    const window = record.get(window_ids, window_id);
    const tabs   = record.get(window, "tabs");

    const tab = make_tab(info, transient);

    record.insert(tab_ids, record.get(tab, "id"), tab);

    list.insert(tabs, index, tab);

    event.send(events, {
      type: "tab-open",
      window,
      tab,
      index
    });
  },

  "tab-focus": (json) => {
    const id = record.get(json, "tab-id");
    const time_focused = record.get(json, "tab-time-focused");

    const tab = record.get(tab_ids, id);

    record.update(tab, "focused", true);
    // TODO test this
    record.assign(record.get(tab, "time"), "focused", time_focused);

    event.send(events, {
      type: "tab-focus",
      tab
    });
  },

  "tab-unfocus": (json) => {
    const id = record.get(json, "tab-id");

    const tab = record.get(tab_ids, id);

    record.update(tab, "focused", false);

    event.send(events, {
      type: "tab-unfocus",
      tab
    });
  },

  "tab-update": (json) => {
    const id = record.get(json, "tab-id");
    const url = record.get(json, "tab-url");
    const title = record.get(json, "tab-title");
    const favicon = record.get(json, "tab-favicon");
    const pinned = record.get(json, "tab-pinned");
    const time = record.get(json, "tab-time-updated");

    const tab = record.get(tab_ids, id);

    // TODO code duplication
    record.update(tab, "url", url);
    // TODO maybe this should be server-side ?
    record.update(tab, "title", title || url);
    record.update(tab, "favicon", favicon);
    record.update(tab, "pinned", pinned);
    record.assign(record.get(tab, "time"), "updated", time);

    event.send(events, {
      type: "tab-update",
      tab
    });
  },

  "tab-move": (json) => {
    const old_window_id = record.get(json, "window-old-id");
    const new_window_id = record.get(json, "window-new-id");
    const old_index = record.get(json, "tab-old-index");
    const new_index = record.get(json, "tab-new-index");
    const tab_id = record.get(json, "tab-id");
    const time_moved = record.get(json, "tab-time-moved");

    const old_window = record.get(window_ids, old_window_id);
    const new_window = record.get(window_ids, new_window_id);
    const old_tabs = record.get(old_window, "tabs");
    const new_tabs = record.get(new_window, "tabs");
    const tab = record.get(tab_ids, tab_id);

    // TODO test this
    record.assign(record.get(tab, "time"), "moved", time_moved);

    assert(list.get(old_tabs, old_index) === tab);

    list.remove(old_tabs, old_index);
    list.insert(new_tabs, new_index, tab);

    event.send(events, {
      type: "tab-move",
      tab,
      old_window,
      new_window,
      old_index,
      new_index
    });
  },

  "tab-close": (json) => {
    const window_id = record.get(json, "window-id");
    const tab_id = record.get(json, "tab-id");
    const index = record.get(json, "tab-index");

    const window = record.get(window_ids, window_id);
    const tab = record.get(tab_ids, tab_id);
    const tabs = record.get(window, "tabs");

    record.remove(tab_ids, record.get(tab, "id"));

    assert(list.get(tabs, index) === tab);

    list.remove(tabs, index);

    event.send(events, {
      type: "tab-close",
      window,
      tab,
      index
    });
  },

  "window-open": (json) => {
    const info = record.get(json, "window");
    const index = record.get(json, "window-index");

    assert(list.size(record.get(info, "tabs")) === 0);

    const window = make_window(info, list.make());

    record.insert(window_ids, record.get(window, "id"), window);

    list.insert(windows, index, window);

    event.send(events, {
      type: "window-open",
      window,
      index
    });
  },

  "window-close": (json) => {
    const window_id = record.get(json, "window-id");
    const index = record.get(json, "window-index");

    const window = record.get(window_ids, window_id);

    assert(list.size(record.get(window, "tabs")) === 0);

    record.remove(window_ids, record.get(window, "id"));

    assert(list.get(windows, index) === window);

    list.remove(windows, index);

    event.send(events, {
      type: "window-close",
      window,
      index
    });
  }
});

ports.on_receive(port, (x) => {
  record.get(types, record.get(x, "type"))(x);
});
<|endoftext|>


<commit_before>!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.testBundle=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/**
 * This function will be stringified and then injected into every rewired module.
 * Then you can leak private variables by calling myModule.__get__("myPrivateVar");
 *
 * All variables within this function are namespaced in the arguments array because every
 * var declaration could possibly clash with a variable in the module scope.
 *
 * @param {!String} name name of the variable to retrieve
 * @throws {TypeError}
 * @return {*}
 */
function __get__() {
    arguments.varName = arguments[0];
    if (arguments.varName && typeof arguments.varName === "string") {
        return eval(arguments.varName);
    } else {
        throw new TypeError("__get__ expects a non-empty string");
    }
}

module.exports = __get__;

},{}],2:[function(_dereq_,module,exports){
/**
 * This function will be stringified and then injected into every rewired module.
 * Then you can set private variables by calling myModule.__set__("myPrivateVar", newValue);
 *
 * All variables within this function are namespaced in the arguments array because every
 * var declaration could possibly clash with a variable in the module scope.
 *
 * @param {!String|!Object} varName name of the variable to set
 * @param {String} varValue new value
 * @throws {TypeError}
 * @throws {ReferenceError} When the variable is unknown
 * @return {*}
 */
function __set__() {
    arguments.varName = arguments[0];
    arguments.varValue = arguments[1];
    arguments.src = "";

    if (typeof arguments[0] === "object" && arguments.length === 1) {
        arguments.env = arguments.varName;
        if (!arguments.env || Array.isArray(arguments.env)) {
            throw new TypeError("__set__ expects an object as env");
        }
        for (arguments.varName in arguments.env) {
            if (arguments.env.hasOwnProperty(arguments.varName)) {
                arguments.varValue = arguments.env[arguments.varName];
                arguments.src += arguments.varName + " = arguments.env." + arguments.varName + "; ";
            }
        }
    } else if (typeof arguments.varName === "string" && arguments.length === 2) {
        if (!arguments.varName) {
            throw new TypeError("__set__ expects a non-empty string as a variable name");
        }
        arguments.src = arguments.varName + " = arguments.varValue;";
    } else {
        throw new TypeError("__set__ expects an environment object or a non-empty string as a variable name");
    }

    eval(arguments.src);
}

module.exports = __set__;

},{}],3:[function(_dereq_,module,exports){
/* This code was injected by Rewireify */
var __getter = _dereq_("/Users/matt/Code/rewireify/lib/__get__").toString();
var __setter = _dereq_("/Users/matt/Code/rewireify/lib/__set__").toString();
exports.exampleMethod = function() {
  return "I am an example";
};

eval(__getter);
eval(__setter);
module.exports.__get__ = __get__;
module.exports.__set__ = __set__;

},{"/Users/matt/Code/rewireify/lib/__get__":1,"/Users/matt/Code/rewireify/lib/__set__":2}],4:[function(_dereq_,module,exports){
/* This code was injected by Rewireify */
var __getter = _dereq_("/Users/matt/Code/rewireify/lib/__get__").toString();
var __setter = _dereq_("/Users/matt/Code/rewireify/lib/__set__").toString();
var privateVariable = "I am private";

var privateDependency = _dereq_("./dependency");

exports.methodUsingDependency = function() {
  return privateDependency.exampleMethod();
};

eval(__getter);
eval(__setter);
module.exports.__get__ = __get__;
module.exports.__set__ = __set__;

},{"./dependency":3,"/Users/matt/Code/rewireify/lib/__get__":1,"/Users/matt/Code/rewireify/lib/__set__":2}]},{},[4])
(4)
});<commit_msg>Cleanup unused test fixtures<commit_after><|endoftext|>


<commit_before>// reduce.js

"use strict";
<commit_msg>Add reduce() with anonymous in-line function<commit_after>// reduce.js

"use strict";

/**
 * reduce() with anonymous in-line function
 */

function animals() {
  let animals = ["cat", "dog", "fish"];

  let total = animals.reduce( (sum, word) => {
    console.log(`sum: ${sum}, word: ${word}`);

    return sum + word.length;
  }, 0);

  console.log(`animals(): ${total} ${animals}`);
}

animals();
<|endoftext|>


<commit_before>// test/variety/amibo_test.js

var assert = require('assert');

var pzpr = require('../../');

var puzzle = new pzpr.Puzzle();

describe('Variety:amibo',function(){
	it('Check area generating', function(){
		puzzle.open('amibo/5/5');

		puzzle.setMode('edit');
		puzzle.cursor.init(1,1);
		puzzle.key.inputKeys('2','down','down','3');

		puzzle.setMode('play');
		puzzle.mouse.inputPath(1,1, 6,1);
		puzzle.mouse.inputPath('right', 6,1);
		puzzle.mouse.inputPath(3,5, 7,5);
		puzzle.mouse.inputPath('right', 8,5);

		assert.equal(puzzle.board.bargraph.components.length, 2);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.setMode('edit');
		puzzle.cursor.init(9,1);
		puzzle.key.inputKeys('4');

		puzzle.setMode('play');
		puzzle.mouse.inputPath(9,1, 9,9);

		assert.equal(puzzle.board.bargraph.components.length, 3);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		puzzle.setMode('edit');
		puzzle.mouse.inputPath(3,3);
		puzzle.mouse.inputPath(3,3);
		puzzle.mouse.inputPath(5,7);
		puzzle.mouse.inputPath(5,7);
		puzzle.mouse.inputPath(7,7);
		puzzle.key.inputKeys('3');

		puzzle.setMode('play');
		puzzle.mouse.inputPath('right', 6,7, 7,8, 8,7);
		puzzle.mouse.inputPath(7,7, 7,0);

		assert.equal(puzzle.board.bargraph.components.length, 4);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		puzzle.mouse.inputPath(5,0, 5,4);
		puzzle.mouse.inputPath('right', 5,4);
		puzzle.mouse.inputPath(5,3, 7,3);
		puzzle.mouse.inputPath('right', 3,2, 2,3, 3,4, 3,6, 1,6, 1,4, 1,8);
		puzzle.mouse.inputPath('right', 5,6, 5,8);

		assert.equal(puzzle.board.bargraph.components.length, 6);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.mouse.inputPath(0,7, 4,7);
		puzzle.mouse.inputPath(3,7, 3,9);

		assert.equal(puzzle.board.bargraph.components.length, 8);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		require('fs').writeFile('./amibo.svg', puzzle.toBuffer());

		puzzle.mouse.inputPath(2,9, 9,9);

		assert.equal(puzzle.board.bargraph.components.length, 9);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.mouse.inputPath(8.5,3, 9.5,3);

		assert.equal(puzzle.board.bargraph.components.length, 9);
		assert.equal(puzzle.board.netgraph.components.length, 1);
		assert.equal(puzzle.check().complete, true);
	});
});
<commit_msg>test: Ensure to delete temporary svg file<commit_after>// test/variety/amibo_test.js

var assert = require('assert');

var pzpr = require('../../');

var puzzle = new pzpr.Puzzle();

describe('Variety:amibo',function(){
	it('Check area generating', function(){
		puzzle.open('amibo/5/5');

		puzzle.setMode('edit');
		puzzle.cursor.init(1,1);
		puzzle.key.inputKeys('2','down','down','3');

		puzzle.setMode('play');
		puzzle.mouse.inputPath(1,1, 6,1);
		puzzle.mouse.inputPath('right', 6,1);
		puzzle.mouse.inputPath(3,5, 7,5);
		puzzle.mouse.inputPath('right', 8,5);

		assert.equal(puzzle.board.bargraph.components.length, 2);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.setMode('edit');
		puzzle.cursor.init(9,1);
		puzzle.key.inputKeys('4');

		puzzle.setMode('play');
		puzzle.mouse.inputPath(9,1, 9,9);

		assert.equal(puzzle.board.bargraph.components.length, 3);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		puzzle.setMode('edit');
		puzzle.mouse.inputPath(3,3);
		puzzle.mouse.inputPath(3,3);
		puzzle.mouse.inputPath(5,7);
		puzzle.mouse.inputPath(5,7);
		puzzle.mouse.inputPath(7,7);
		puzzle.key.inputKeys('3');

		puzzle.setMode('play');
		puzzle.mouse.inputPath('right', 6,7, 7,8, 8,7);
		puzzle.mouse.inputPath(7,7, 7,0);

		assert.equal(puzzle.board.bargraph.components.length, 4);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		puzzle.mouse.inputPath(5,0, 5,4);
		puzzle.mouse.inputPath('right', 5,4);
		puzzle.mouse.inputPath(5,3, 7,3);
		puzzle.mouse.inputPath('right', 3,2, 2,3, 3,4, 3,6, 1,6, 1,4, 1,8);
		puzzle.mouse.inputPath('right', 5,6, 5,8);

		assert.equal(puzzle.board.bargraph.components.length, 6);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.mouse.inputPath(0,7, 4,7);
		puzzle.mouse.inputPath(3,7, 3,9);

		assert.equal(puzzle.board.bargraph.components.length, 8);
		assert.equal(puzzle.board.netgraph.components.length, 3);

		require('fs').writeFileSync('./amibo.svg', puzzle.toBuffer());
		require('fs').unlinkSync('./amibo.svg');

		puzzle.mouse.inputPath(2,9, 9,9);

		assert.equal(puzzle.board.bargraph.components.length, 9);
		assert.equal(puzzle.board.netgraph.components.length, 2);

		puzzle.mouse.inputPath(8.5,3, 9.5,3);

		assert.equal(puzzle.board.bargraph.components.length, 9);
		assert.equal(puzzle.board.netgraph.components.length, 1);
		assert.equal(puzzle.check().complete, true);
	});
});
<|endoftext|>