<commit_before>const JlSql = require('../..');
const assert = require('assert');

const jlSql = new JlSql;

describe('SELECT', () => {
	describe('`SELECT * WHERE ...`', () => {
		const input = [{hello: "world"}, {hello: "hello"}];

		let output;

		before(done => {
			jlSql.query('SELECT * WHERE hello = "hello"')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('filters', () => {
			assert.strictEqual(output.length, 1);
			assert.strictEqual(output[0].hello, 'hello');
		});

		it('return same objects', () => {
			assert.strictEqual(output[0], input[1]);
		});
	});

	describe('`SELECT [field[, ...]]`', () => {
		const input = [{f1: "11", f2: "12", f3: "13"}];

		let output;

		before(done => {
			jlSql.query('SELECT f1, f2')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('returns new objects', () => {
			assert.notDeepStrictEqual(output[0], input[0]);
		});

		it('make right properties', () => {
			assert.strictEqual(output[0].f1, '11');
			assert.strictEqual(output[0].f2, '12');
			assert.strictEqual(output[0].f3, undefined);
		});

		it('original objects was not updated', () => {
			assert.strictEqual(input[0].f1, '11');
			assert.strictEqual(input[0].f2, '12');
			assert.strictEqual(input[0].f3, '13');
		});
	});

	describe('`SELECT ... ORDER BY [field[, ...]]`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT * ORDER BY a, b DESC')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('ordered', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, b: 5},
					{a: 1, b: 3},
					{a: 2, b: 2},
					{a: 3, b: 6},
					{a: 3, b: 4}
				]
			);
		});
	});

	describe('`SELECT ... GROUP BY [field[, ...]]`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT a, COUNT(*) AS count GROUP BY a')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('aggregated and ordered', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, count: 2},
					{a: 2, count: 1},
					{a: 3, count: 2}
				]
			);
		});
	});

	describe('`SELECT ... GROUP BY ... HAVING ...`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT a, COUNT(*) AS count GROUP BY a HAVING count > 1')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('make right result', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, count: 2},
					{a: 3, count: 2}
				]
			);
		});
	});
});
<commit_msg>Tests for `AS` (aliases)<commit_after>const JlSql = require('../..');
const assert = require('assert');

const jlSql = new JlSql;

describe('SELECT', () => {
	describe('`SELECT * WHERE ...`', () => {
		const input = [{hello: "world"}, {hello: "hello"}];

		let output;

		before(done => {
			jlSql.query('SELECT * WHERE hello = "hello"')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('filters', () => {
			assert.strictEqual(output.length, 1);
			assert.strictEqual(output[0].hello, 'hello');
		});

		it('return same objects', () => {
			assert.strictEqual(output[0], input[1]);
		});
	});

	describe('`SELECT [field[, ...]]`', () => {
		const input = [{f1: "11", f2: "12", f3: "13"}];

		let output;

		before(done => {
			jlSql.query('SELECT f1, f2')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('returns new objects', () => {
			assert.notDeepStrictEqual(output[0], input[0]);
		});

		it('make right properties', () => {
			assert.strictEqual(output[0].f1, '11');
			assert.strictEqual(output[0].f2, '12');
			assert.strictEqual(output[0].f3, undefined);
		});

		it('original objects was not updated', () => {
			assert.strictEqual(input[0].f1, '11');
			assert.strictEqual(input[0].f2, '12');
			assert.strictEqual(input[0].f3, '13');
		});
	});

	describe('`SELECT ... ORDER BY [field[, ...]]`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT * ORDER BY a, b DESC')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('ordered', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, b: 5},
					{a: 1, b: 3},
					{a: 2, b: 2},
					{a: 3, b: 6},
					{a: 3, b: 4}
				]
			);
		});
	});

	describe('`SELECT ... GROUP BY [field[, ...]]`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT a, COUNT(*) AS count GROUP BY a')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('aggregated and ordered', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, count: 2},
					{a: 2, count: 1},
					{a: 3, count: 2}
				]
			);
		});
	});

	describe('`SELECT ... GROUP BY ... HAVING ...`', () => {
		const input = [
			{a: 2, b: 2},
			{a: 1, b: 3},
			{a: 3, b: 6},
			{a: 3, b: 4},
			{a: 1, b: 5}
		];

		let output;

		before(done => {
			jlSql.query('SELECT a, COUNT(*) AS count GROUP BY a HAVING count > 1')
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('make right result', () => {
			assert.deepEqual(
				output,
				[
					{a: 1, count: 2},
					{a: 3, count: 2}
				]
			);
		});
	});

	describe('`SELECT ... AS alias[.deepAlias[. ...]]`', () => {
		const input = [{a: 10}];

		let output;

		before(done => {
			jlSql.query(
					`SELECT
						a,
						a AS aliasForA,
						aliasForA AS nonexistentAlias,
						a + 10 AS b,
						a + 20 AS deep.c,
						a + 30 AS deep.d.e,
						undef AS deepUndef.undef`
				)
				.fromArrayOfObjects(input)
				.toArrayOfObjects((r) => {
					output = r;
					done();
				})
			;
		});

		it('original column', () => {
			assert.strictEqual(output[0].a, input[0].a);
		});

		it('alias to alias', () => {
			assert.strictEqual(output[0].nonexistentAlias, undefined);
		})

		it('direct column to alias mapping', () => {
			assert.strictEqual(output[0].aliasForA, input[0].a);
		});

		it('aliases to top level', () => {
			assert.strictEqual(output[0].b, input[0].a + 10);
		});

		it('aliases to deep levels', () => {
			assert.strictEqual(output[0].deep.c, input[0].a + 20);
			assert.strictEqual(output[0].deep.d.e, input[0].a + 30);
		});

		it('alias to undefined does not make empty deep object', () => {
			assert.strictEqual(output[0].deepUndef, undefined);
		})
	});
});
<|endoftext|>


<commit_before>import reducer from 'src/data_explorer/reducers/queryConfigs'
import defaultQueryConfig from 'src/utils/defaultQueryConfig'
import {
  chooseNamespace,
  chooseMeasurement,
  toggleField,
  applyFuncsToField,
  chooseTag,
  groupByTag,
  groupByTime,
  toggleTagAcceptance,
  fill,
  updateQueryConfig,
  updateRawQuery,
  editQueryStatus,
} from 'src/data_explorer/actions/view'

import {LINEAR, NULL_STRING} from 'shared/constants/queryFillOptions'

const fakeAddQueryAction = (panelID, queryID) => {
  return {
    type: 'DE_ADD_QUERY',
    payload: {panelID, queryID},
  }
}

function buildInitialState(queryId, params) {
  return Object.assign({}, defaultQueryConfig({id: queryId}), params)
}

describe('Chronograf.Reducers.DataExplorer.queryConfigs', () => {
  const queryId = 123

  it('can add a query', () => {
    const state = reducer({}, fakeAddQueryAction('blah', queryId))

    const actual = state[queryId]
    const expected = defaultQueryConfig({id: queryId})
    expect(actual).to.deep.equal(expected)
  })

  describe('choosing db, rp, and measurement', () => {
    let state
    beforeEach(() => {
      state = reducer({}, fakeAddQueryAction('any', queryId))
    })

    it('sets the db and rp', () => {
      const newState = reducer(
        state,
        chooseNamespace(queryId, {
          database: 'telegraf',
          retentionPolicy: 'monitor',
        })
      )

      expect(newState[queryId].database).to.equal('telegraf')
      expect(newState[queryId].retentionPolicy).to.equal('monitor')
    })

    it('sets the measurement', () => {
      const newState = reducer(state, chooseMeasurement(queryId, 'mem'))

      expect(newState[queryId].measurement).to.equal('mem')
    })
  })

  describe('a query has measurements and fields', () => {
    let state
    beforeEach(() => {
      const one = reducer({}, fakeAddQueryAction('any', queryId))
      const two = reducer(
        one,
        chooseNamespace(queryId, {
          database: '_internal',
          retentionPolicy: 'daily',
        })
      )
      const three = reducer(two, chooseMeasurement(queryId, 'disk'))
      state = reducer(
        three,
        toggleField(queryId, {field: 'a great field', funcs: []})
      )
    })

    describe('choosing a new namespace', () => {
      it('clears out the old measurement and fields', () => {
        // what about tags?
        expect(state[queryId].measurement).to.exist
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          chooseNamespace(queryId, {
            database: 'newdb',
            retentionPolicy: 'newrp',
          })
        )

        expect(newState[queryId].measurement).not.to.exist
        expect(newState[queryId].fields.length).to.equal(0)
      })
    })

    describe('choosing a new measurement', () => {
      it('leaves the namespace and clears out the old fields', () => {
        // what about tags?
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          chooseMeasurement(queryId, 'newmeasurement')
        )

        expect(state[queryId].database).to.equal(newState[queryId].database)
        expect(state[queryId].retentionPolicy).to.equal(
          newState[queryId].retentionPolicy
        )
        expect(newState[queryId].fields.length).to.equal(0)
      })
    })

    describe('DE_TOGGLE_FIELD', () => {
      it('can toggle multiple fields', () => {
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          toggleField(queryId, {field: 'a different field', funcs: []})
        )

        expect(newState[queryId].fields.length).to.equal(2)
        expect(newState[queryId].fields[1].field).to.equal('a different field')
      })

      it('applies a funcs to newly selected fields', () => {
        expect(state[queryId].fields.length).to.equal(1)

        const oneFieldOneFunc = reducer(
          state,
          applyFuncsToField(queryId, {field: 'a great field', funcs: ['func1']})
        )

        const newState = reducer(
          oneFieldOneFunc,
          toggleField(queryId, {field: 'a different field', funcs: []})
        )

        expect(newState[queryId].fields[1].funcs.length).to.equal(1)
        expect(newState[queryId].fields[1].funcs[0]).to.equal('func1')
      })

      it('adds the field property to query config if not found', () => {
        delete state[queryId].fields
        expect(state[queryId].fields).to.equal(undefined)

        const field = 'fk1'
        const newState = reducer(
          state,
          toggleField(queryId, {field: 'fk1', funcs: []})
        )

        expect(newState[queryId].fields.length).to.equal(1)
        expect(newState[queryId].fields[0].field).to.equal(field)
      })
    })
  })

  describe('DE_APPLY_FUNCS_TO_FIELD', () => {
    it('applies functions to a field without any existing functions', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [
            {field: 'f1', funcs: ['fn1', 'fn2']},
            {field: 'f2', funcs: ['fn1']},
          ],
        },
      }
      const action = applyFuncsToField(queryId, {
        field: 'f1',
        funcs: ['fn3', 'fn4'],
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fields).to.eql([
        {field: 'f1', funcs: ['fn3', 'fn4']},
        {field: 'f2', funcs: ['fn1']},
      ])
    })

    it('removes all functions and group by time when one field has no funcs applied', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [
            {field: 'f1', funcs: ['fn1', 'fn2']},
            {field: 'f2', funcs: ['fn3', 'fn4']},
          ],
          groupBy: {
            time: '1m',
            tags: [],
          },
        },
      }

      const action = applyFuncsToField(queryId, {
        field: 'f1',
        funcs: [],
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fields).to.eql([
        {field: 'f1', funcs: []},
        {field: 'f2', funcs: []},
      ])
      expect(nextState[queryId].groupBy.time).to.equal(null)
    })
  })

  describe('DE_CHOOSE_TAG', () => {
    it('adds a tag key/value to the query', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {
            k1: ['v0'],
            k2: ['foo'],
          },
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].tags).to.eql({
        k1: ['v0', 'v1'],
        k2: ['foo'],
      })
    })

    it("creates a new entry if it's the first key", () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {},
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].tags).to.eql({
        k1: ['v1'],
      })
    })

    it('removes a value that is already in the list', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {
            k1: ['v1'],
          },
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      // TODO: this should probably remove the `k1` property entirely from the tags object
      expect(nextState[queryId].tags).to.eql({})
    })
  })

  describe('DE_GROUP_BY_TAG', () => {
    it('adds a tag key/value to the query', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [],
          tags: {},
          groupBy: {tags: [], time: null},
        },
      }
      const action = groupByTag(queryId, 'k1')

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy).to.eql({
        time: null,
        tags: ['k1'],
      })
    })

    it('removes a tag if the given tag key is already in the GROUP BY list', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [],
          tags: {},
          groupBy: {tags: ['k1'], time: null},
        },
      }
      const action = groupByTag(queryId, 'k1')

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy).to.eql({
        time: null,
        tags: [],
      })
    })
  })

  describe('DE_TOGGLE_TAG_ACCEPTANCE', () => {
    it('it toggles areTagsAccepted', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const action = toggleTagAcceptance(queryId)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].areTagsAccepted).to.equal(
        !initialState[queryId].areTagsAccepted
      )
    })
  })

  describe('DE_GROUP_BY_TIME', () => {
    it('applys the appropriate group by time', () => {
      const time = '100y'
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }

      const action = groupByTime(queryId, time)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy.time).to.equal(time)
    })
  })

  it('updates entire config', () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const expected = defaultQueryConfig({id: queryId}, {rawText: 'hello'})
    const action = updateQueryConfig(expected)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId]).to.deep.equal(expected)
  })

  it("updates a query's raw text", () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const text = 'foo'
    const action = updateRawQuery(queryId, text)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId].rawText).to.equal('foo')
  })

  it("updates a query's raw status", () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const status = 'your query was sweet'
    const action = editQueryStatus(queryId, status)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId].status).to.equal(status)
  })

  describe('DE_FILL', () => {
    it('applies an explicit fill when group by time is used', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const time = '10s'
      const action = groupByTime(queryId, time)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(NULL_STRING)
    })

    it('updates fill to non-null-string non-number string value', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const action = fill(queryId, LINEAR)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(LINEAR)
    })
  })
})
<commit_msg>Test client DE fill for ints and floats<commit_after>import reducer from 'src/data_explorer/reducers/queryConfigs'
import defaultQueryConfig from 'src/utils/defaultQueryConfig'
import {
  chooseNamespace,
  chooseMeasurement,
  toggleField,
  applyFuncsToField,
  chooseTag,
  groupByTag,
  groupByTime,
  toggleTagAcceptance,
  fill,
  updateQueryConfig,
  updateRawQuery,
  editQueryStatus,
} from 'src/data_explorer/actions/view'

import {LINEAR, NULL_STRING} from 'shared/constants/queryFillOptions'

const fakeAddQueryAction = (panelID, queryID) => {
  return {
    type: 'DE_ADD_QUERY',
    payload: {panelID, queryID},
  }
}

function buildInitialState(queryId, params) {
  return Object.assign({}, defaultQueryConfig({id: queryId}), params)
}

describe('Chronograf.Reducers.DataExplorer.queryConfigs', () => {
  const queryId = 123

  it('can add a query', () => {
    const state = reducer({}, fakeAddQueryAction('blah', queryId))

    const actual = state[queryId]
    const expected = defaultQueryConfig({id: queryId})
    expect(actual).to.deep.equal(expected)
  })

  describe('choosing db, rp, and measurement', () => {
    let state
    beforeEach(() => {
      state = reducer({}, fakeAddQueryAction('any', queryId))
    })

    it('sets the db and rp', () => {
      const newState = reducer(
        state,
        chooseNamespace(queryId, {
          database: 'telegraf',
          retentionPolicy: 'monitor',
        })
      )

      expect(newState[queryId].database).to.equal('telegraf')
      expect(newState[queryId].retentionPolicy).to.equal('monitor')
    })

    it('sets the measurement', () => {
      const newState = reducer(state, chooseMeasurement(queryId, 'mem'))

      expect(newState[queryId].measurement).to.equal('mem')
    })
  })

  describe('a query has measurements and fields', () => {
    let state
    beforeEach(() => {
      const one = reducer({}, fakeAddQueryAction('any', queryId))
      const two = reducer(
        one,
        chooseNamespace(queryId, {
          database: '_internal',
          retentionPolicy: 'daily',
        })
      )
      const three = reducer(two, chooseMeasurement(queryId, 'disk'))
      state = reducer(
        three,
        toggleField(queryId, {field: 'a great field', funcs: []})
      )
    })

    describe('choosing a new namespace', () => {
      it('clears out the old measurement and fields', () => {
        // what about tags?
        expect(state[queryId].measurement).to.exist
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          chooseNamespace(queryId, {
            database: 'newdb',
            retentionPolicy: 'newrp',
          })
        )

        expect(newState[queryId].measurement).not.to.exist
        expect(newState[queryId].fields.length).to.equal(0)
      })
    })

    describe('choosing a new measurement', () => {
      it('leaves the namespace and clears out the old fields', () => {
        // what about tags?
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          chooseMeasurement(queryId, 'newmeasurement')
        )

        expect(state[queryId].database).to.equal(newState[queryId].database)
        expect(state[queryId].retentionPolicy).to.equal(
          newState[queryId].retentionPolicy
        )
        expect(newState[queryId].fields.length).to.equal(0)
      })
    })

    describe('DE_TOGGLE_FIELD', () => {
      it('can toggle multiple fields', () => {
        expect(state[queryId].fields.length).to.equal(1)

        const newState = reducer(
          state,
          toggleField(queryId, {field: 'a different field', funcs: []})
        )

        expect(newState[queryId].fields.length).to.equal(2)
        expect(newState[queryId].fields[1].field).to.equal('a different field')
      })

      it('applies a funcs to newly selected fields', () => {
        expect(state[queryId].fields.length).to.equal(1)

        const oneFieldOneFunc = reducer(
          state,
          applyFuncsToField(queryId, {field: 'a great field', funcs: ['func1']})
        )

        const newState = reducer(
          oneFieldOneFunc,
          toggleField(queryId, {field: 'a different field', funcs: []})
        )

        expect(newState[queryId].fields[1].funcs.length).to.equal(1)
        expect(newState[queryId].fields[1].funcs[0]).to.equal('func1')
      })

      it('adds the field property to query config if not found', () => {
        delete state[queryId].fields
        expect(state[queryId].fields).to.equal(undefined)

        const field = 'fk1'
        const newState = reducer(
          state,
          toggleField(queryId, {field: 'fk1', funcs: []})
        )

        expect(newState[queryId].fields.length).to.equal(1)
        expect(newState[queryId].fields[0].field).to.equal(field)
      })
    })
  })

  describe('DE_APPLY_FUNCS_TO_FIELD', () => {
    it('applies functions to a field without any existing functions', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [
            {field: 'f1', funcs: ['fn1', 'fn2']},
            {field: 'f2', funcs: ['fn1']},
          ],
        },
      }
      const action = applyFuncsToField(queryId, {
        field: 'f1',
        funcs: ['fn3', 'fn4'],
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fields).to.eql([
        {field: 'f1', funcs: ['fn3', 'fn4']},
        {field: 'f2', funcs: ['fn1']},
      ])
    })

    it('removes all functions and group by time when one field has no funcs applied', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [
            {field: 'f1', funcs: ['fn1', 'fn2']},
            {field: 'f2', funcs: ['fn3', 'fn4']},
          ],
          groupBy: {
            time: '1m',
            tags: [],
          },
        },
      }

      const action = applyFuncsToField(queryId, {
        field: 'f1',
        funcs: [],
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fields).to.eql([
        {field: 'f1', funcs: []},
        {field: 'f2', funcs: []},
      ])
      expect(nextState[queryId].groupBy.time).to.equal(null)
    })
  })

  describe('DE_CHOOSE_TAG', () => {
    it('adds a tag key/value to the query', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {
            k1: ['v0'],
            k2: ['foo'],
          },
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].tags).to.eql({
        k1: ['v0', 'v1'],
        k2: ['foo'],
      })
    })

    it("creates a new entry if it's the first key", () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {},
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].tags).to.eql({
        k1: ['v1'],
      })
    })

    it('removes a value that is already in the list', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId, {
          tags: {
            k1: ['v1'],
          },
        }),
      }
      const action = chooseTag(queryId, {
        key: 'k1',
        value: 'v1',
      })

      const nextState = reducer(initialState, action)

      // TODO: this should probably remove the `k1` property entirely from the tags object
      expect(nextState[queryId].tags).to.eql({})
    })
  })

  describe('DE_GROUP_BY_TAG', () => {
    it('adds a tag key/value to the query', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [],
          tags: {},
          groupBy: {tags: [], time: null},
        },
      }
      const action = groupByTag(queryId, 'k1')

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy).to.eql({
        time: null,
        tags: ['k1'],
      })
    })

    it('removes a tag if the given tag key is already in the GROUP BY list', () => {
      const initialState = {
        [queryId]: {
          id: 123,
          database: 'db1',
          measurement: 'm1',
          fields: [],
          tags: {},
          groupBy: {tags: ['k1'], time: null},
        },
      }
      const action = groupByTag(queryId, 'k1')

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy).to.eql({
        time: null,
        tags: [],
      })
    })
  })

  describe('DE_TOGGLE_TAG_ACCEPTANCE', () => {
    it('it toggles areTagsAccepted', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const action = toggleTagAcceptance(queryId)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].areTagsAccepted).to.equal(
        !initialState[queryId].areTagsAccepted
      )
    })
  })

  describe('DE_GROUP_BY_TIME', () => {
    it('applys the appropriate group by time', () => {
      const time = '100y'
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }

      const action = groupByTime(queryId, time)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].groupBy.time).to.equal(time)
    })
  })

  it('updates entire config', () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const expected = defaultQueryConfig({id: queryId}, {rawText: 'hello'})
    const action = updateQueryConfig(expected)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId]).to.deep.equal(expected)
  })

  it("updates a query's raw text", () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const text = 'foo'
    const action = updateRawQuery(queryId, text)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId].rawText).to.equal('foo')
  })

  it("updates a query's raw status", () => {
    const initialState = {
      [queryId]: buildInitialState(queryId),
    }
    const status = 'your query was sweet'
    const action = editQueryStatus(queryId, status)

    const nextState = reducer(initialState, action)

    expect(nextState[queryId].status).to.equal(status)
  })

  describe('DE_FILL', () => {
    it('applies an explicit fill when group by time is used', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const time = '10s'
      const action = groupByTime(queryId, time)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(NULL_STRING)
    })

    it('updates fill to non-null-string non-number string value', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const action = fill(queryId, LINEAR)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(LINEAR)
    })

    it('updates fill to string integer value', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const INT_STRING = '1337'
      const action = fill(queryId, INT_STRING)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(INT_STRING)
    })

    it('updates fill to string float value', () => {
      const initialState = {
        [queryId]: buildInitialState(queryId),
      }
      const FLOAT_STRING = '1.337'
      const action = fill(queryId, FLOAT_STRING)

      const nextState = reducer(initialState, action)

      expect(nextState[queryId].fill).to.equal(FLOAT_STRING)
    })
  })
})
<|endoftext|>


<commit_before>/* globals $ */
var nameChecker = function() {
  var btnText = $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
    .text();
  var initAction = '$(".a-js-validator").find("input[type=text]")' +
      '.attr("disabled", "disabled").parent().addClass("disabled")' +
      '.addClass("a-input-approved");' +
    '$(".a-js-validator").find(".a-validatorInfo").eq(0).hide();' +
    '$(".a-js-validator").find(".a-validatorInfo").eq(1).show();' +
    '$(".a-js-validator").find(".a-btn-group").find(".a-btn").eq(0)' +
      '.html("Velg navn").removeAttr("onclick")' +
      '.addClass("a-js-smoothStateEnabled");' +
    '$(".a-js-tryAnother").show();' +
    'window.smoothStateMod();';
  $('.a-js-validator').find('.a-validatorInfo').eq(1).find('i')
    .addClass('a-validatorInfo-icon-approved');
  $('.a-js-validator').find('.a-validatorInfo').css('display', 'inline-block')
    .eq(1)
    .hide();
  if ($('.a-js-tryAnother').length === 0) {
    $('<button/>', {
      type: 'button',
      class: 'a-btn-link a-js-tryAnother',
      text: 'Prøv et annet navn'
    }).appendTo('.a-btn-group', '.a-js-validator');
  }
  $('.a-js-tryAnother').hide().on('click', function() {
    $('.a-js-validator').find('input[type=text]').removeAttr('disabled')
    .parent()
    .removeClass('disabled')
    .removeClass('a-input-approved');
    $('.a-js-tryAnother').hide();
    $('.a-js-validator').find('.a-validatorInfo').eq(0).show();
    $('.a-js-validator').find('.a-validatorInfo').eq(1).hide();
    $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
    .html(btnText)
    .removeClass('a-js-smoothStateEnabled')
    .attr('onclick', '$(".a-js-validator").find(".a-message-error").show()')
    .hide();
    $('.a-js-validator').find('input[type=text]').val('');
    $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
    .show();
  });
  $('.a-js-validator').find('.a-message-error');
  function toggleBtns(el) {
    if ($(el).length > 0 && $(el).val().length > 0) {
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .show();
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
        .hide();
      if (
        $('.a-js-validator').find('input[type=text]').val()
          .indexOf($('.a-personSwitcher-name').attr('title').toLowerCase()
          .split(' ')[1]) !== -1 ||
        $('.a-js-validator').find('input[type=text]').val()
          .indexOf($('.a-personSwitcher-name').attr('title')
          .split(' ')[1]) !== -1
      ) {
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .attr('onclick', initAction);
      } else {
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .attr('onclick',
            '$(".a-js-validator").find(".a-message-error").show()');
      }
    } else {
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .hide();
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
        .show();
    }
  }
  toggleBtns($('.a-js-validator').find('input[type=text]'));
  $('.a-js-validator').find('input[type=text]').on('keyup', function(e) {
    if (e.which !== 13) {
      $('.a-js-validator').find('.a-message-error').hide();
    }
    toggleBtns(this);
  });
  $('.a-js-validator').find('input[type=text]').on('keydown', function(e) {
    $('.a-js-validator').find('.a-message-error').hide();
    if (e.which === 13) {
      e.preventDefault(); e.stopPropagation();
      if ($('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .is(':visible')) {
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .click();
      }
    }
  });
  $('.a-js-validator').find('input[type=text]').on('change', function() {
    $('.a-js-validator').find('.a-message-error').hide();
    toggleBtns(this);
  });
};
<commit_msg>Bugfix<commit_after>/* globals $ */
var nameChecker = function() {
  var btnText; var initAction; var toggleBtns;
  if ($('.a-js-validator').length > 0) {
    btnText = $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
    .text();
    initAction = '$(".a-js-validator").find("input[type=text]")' +
    '.attr("disabled", "disabled").parent().addClass("disabled")' +
    '.addClass("a-input-approved");' +
    '$(".a-js-validator").find(".a-validatorInfo").eq(0).hide();' +
    '$(".a-js-validator").find(".a-validatorInfo").eq(1).show();' +
    '$(".a-js-validator").find(".a-btn-group").find(".a-btn").eq(0)' +
    '.html("Velg navn").removeAttr("onclick")' +
    '.addClass("a-js-smoothStateEnabled");' +
    '$(".a-js-tryAnother").show();' +
    'window.smoothStateMod();';
    $('.a-js-validator').find('.a-validatorInfo').eq(1).find('i')
    .addClass('a-validatorInfo-icon-approved');
    $('.a-js-validator').find('.a-validatorInfo').css('display', 'inline-block')
    .eq(1)
    .hide();
    if ($('.a-js-tryAnother').length === 0) {
      $('<button/>', {
        type: 'button',
        class: 'a-btn-link a-js-tryAnother',
        text: 'Prøv et annet navn'
      }).appendTo('.a-btn-group', '.a-js-validator');
    }
    $('.a-js-tryAnother').hide().on('click', function() {
      $('.a-js-validator').find('input[type=text]').removeAttr('disabled')
      .parent()
      .removeClass('disabled')
      .removeClass('a-input-approved');
      $('.a-js-tryAnother').hide();
      $('.a-js-validator').find('.a-validatorInfo').eq(0).show();
      $('.a-js-validator').find('.a-validatorInfo').eq(1).hide();
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
      .html(btnText)
      .removeClass('a-js-smoothStateEnabled')
      .attr('onclick', '$(".a-js-validator").find(".a-message-error").show()')
      .hide();
      $('.a-js-validator').find('input[type=text]').val('');
      $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
      .show();
    });
    $('.a-js-validator').find('.a-message-error');
    toggleBtns = function(el) {
      if ($(el).length > 0 && $(el).val().length > 0) {
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .show();
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
        .hide();
        if (
          $('.a-js-validator').find('input[type=text]').val()
          .indexOf($('.a-personSwitcher-name').attr('title').toLowerCase()
          .split(' ')[1]) !== -1 ||
          $('.a-js-validator').find('input[type=text]').val()
          .indexOf($('.a-personSwitcher-name').attr('title')
          .split(' ')[1]) !== -1
        ) {
          $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .attr('onclick', initAction);
        } else {
          $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .attr('onclick',
          '$(".a-js-validator").find(".a-message-error").show()');
        }
      } else {
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .hide();
        $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(1)
        .show();
      }
    };
    toggleBtns($('.a-js-validator').find('input[type=text]'));
    $('.a-js-validator').find('input[type=text]').on('keyup', function(e) {
      if (e.which !== 13) {
        $('.a-js-validator').find('.a-message-error').hide();
      }
      toggleBtns(this);
    });
    $('.a-js-validator').find('input[type=text]').on('keydown', function(e) {
      $('.a-js-validator').find('.a-message-error').hide();
      if (e.which === 13) {
        e.preventDefault(); e.stopPropagation();
        if ($('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
        .is(':visible')) {
          $('.a-js-validator').find('.a-btn-group').find('.a-btn').eq(0)
          .click();
        }
      }
    });
    $('.a-js-validator').find('input[type=text]').on('change', function() {
      $('.a-js-validator').find('.a-message-error').hide();
      toggleBtns(this);
    });
  }
};
<|endoftext|>


<commit_before>import {maxBy} from 'lodash';
import Promise from 'bluebird';

/**
 * Controller for handling the dialog to add a new pokemon
 * @return {function} A controller that contains 2 test elements
 */
module.exports = function ($mdDialog, $routeParams) {
  this.visibilities = require('../../api/services/Constants.js').POKEMON_VISIBILITIES;
  this.defaultBox = undefined;

  if (this.boxes.length) {
    this.defaultBox =
      $routeParams.boxid && this.boxes.map(box => box.id).includes($routeParams.boxid)
        ? $routeParams.boxid
        : maxBy(this.boxes, box => +new Date(box.updatedAt)).id;
  }

  this.lines = [];

  this.addLine = (line) => this.lines.push(line);

  this.addFiles = (files) => {
    files.forEach(file => this.addLine({
      filename: file.name,
      data: fileToBase64(file),
      visibility: this.defaultPokemonVisibility,
      box: this.defaultBox
    }));
    this.draggedFiles = [];
    this.manualFiles = [];
  };

  this.cancel = function() {
    return $mdDialog.cancel();
  };

  this.canAdd = function () {
    return this.lines.every((line) => line.visibility && line.data && line.box);
  };

  this.answer = function() {
    return $mdDialog.hide(this.lines);
  };
};

function fileToBase64 (file) {
  return new Promise((resolve, reject) => {
    const fr = new FileReader();
    fr.onload = evt => {
      resolve(btoa(
        new Uint8Array(evt.target.result).reduce((acc, next) => acc + String.fromCharCode(next), '')
      ));
    };
    fr.onerror = reject;
    fr.readAsArrayBuffer(file);
  });
}
<commit_msg>Use prototype functions in add/pokemon.ctrl.js<commit_after>import {maxBy} from 'lodash';
import Promise from 'bluebird';

/**
 * Controller for handling the dialog to add a new pokemon
 * @return {function} A controller that contains 2 test elements
 */

module.exports = class PokemonAdd {
  constructor ($mdDialog, $routeParams) {
    this.$mdDialog = $mdDialog;
    this.$routeParams = $routeParams;

    this.visibilities = require('../../api/services/Constants').POKEMON_VISIBILITIES;
    this.defaultBox = undefined;
    if (this.boxes.length) {
      this.defaultBox =
        this.$routeParams.boxid && this.boxes.map(box => box.id).includes(this.$routeParams.boxid)
          ? this.$routeParams.boxid
          : maxBy(this.boxes, box => +new Date(box.updatedAt)).id;
    }
    this.lines = [];
  }

  addLine (line) {
    this.lines.push(line);
  }

  addFiles (files) {
    files.forEach(file => this.addLine({
      filename: file.name,
      data: fileToBase64(file),
      visibility: this.defaultPokemonVisibility,
      box: this.defaultBox
    }));
    this.draggedFiles = [];
    this.manualFiles = [];
  }

  cancel () {
    return this.$mdDialog.cancel();
  }

  canAdd () {
    return this.lines.every((line) => line.visibility && line.data && line.box);
  }
  answer () {
    return this.$mdDialog.hide(this.lines);
  }
};

function fileToBase64 (file) {
  return new Promise((resolve, reject) => {
    const fr = new FileReader();
    fr.onload = evt => {
      resolve(btoa(
        new Uint8Array(evt.target.result).reduce((acc, next) => acc + String.fromCharCode(next), '')
      ));
    };
    fr.onerror = reject;
    fr.readAsArrayBuffer(file);
  });
}
<|endoftext|>


<commit_before>function buzzoff(){

	var stories = document.getElementsByClassName("_4-u2 mbm _5jmm _5pat _5v3q _5x16 _x72");
	//alert(stories);
	var story;
	for(var i=0; i < stories.length; i++){
		story = stories[i];
		killStories(story);
	}

	stories = document.getElementsByClassName("_4-u2 mbm _5jmm _5pat _5v3q _5x16");
	//alert(stories);
	for(var j=0; i < stories.length; i++){
		story = stories[j];
		killStories(story);
	}

	stories = document.getElementsByClassName("timelineUnitContainer pagesTimelinePinpost");
	//alert(stories);
	//alert(stories[0].toString());
	for(var k=0; i < stories.length; i++){
		story = stories[k];
		killStories(story);
	}

	stories = document.getElementsByClassName("timelineUnitContainer");
	//alert(stories);
	//alert(stories[0].toString());
	for(var l=0; i < stories.length; i++){
		story = stories[l];
		killStories(story);
	}

}

function killStories(item){

	var elems = item.getElementsByClassName("fsm fwn fcg");

	var post;
	for(var i=0; i < elems.length; i++){
	    post = elems[i];
	    alert(post.innerHTML)

	    if (post.value.toString().indexOf("buzzfeed.com") !== -1){
	    	item.style.opacity = "0.0";
	    	item.style.display = "None";
    	}

	}
}

buzzoff();

<commit_msg>Updated so it works<commit_after>function buzzoff(){

	var stories = document.querySelectorAll("._4-u2");
	var story;
	alert(stories.length);
	for(var i=0; i < stories.length; i++){
		story = stories[i];
		if (story.value.toString().indexOf("buzzfeed.com") !== -1){
			killStories(story);
		}
	}

	// stories = document.getElementsByClassName("_4-u2 mbm _5jmm _5pat _5v3q _5x16");
	// //alert(stories);
	// for(var j=0; i < stories.length; i++){
	// 	story = stories[j];
	// 	killStories(story);
	// }

	// stories = document.getElementsByClassName("timelineUnitContainer pagesTimelinePinpost");
	// //alert(stories);
	// //alert(stories[0].toString());
	// for(var k=0; i < stories.length; i++){
	// 	story = stories[k];
	// 	killStories(story);
	// }

	// stories = document.getElementsByClassName("timelineUnitContainer");
	// //alert(stories);
	// //alert(stories[0].toString());
	// for(var l=0; i < stories.length; i++){
	// 	story = stories[l];
	// 	killStories(story);
	// }

}

function killStories(item){

	// var post;
	// post = item;
	// for(var i=0; i < elems.length; i++){
	//     post = elems[i];
	    alert(item.innerHTML);

	   //if (item.value.toString().indexOf("buzzfeed.com") !== -1){
	    	item.style.opacity = "0.0";
	    	item.style.display = "None";
    	//}

	//}
}

buzzoff();

<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import styled from 'styled-components';

import Avatar from '../components/Avatar';
import CardContent from '../components/CardContent';
import ReportButton from './ReportButton';
import ReportList from './ReportList';
import ReportText from './ReportText';

const userPhotoUrl = '../../images/animals/bat.png';

const CardContentTab = styled.div`
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    font-size: 0.8rem;
`;

const DarkBackGround = styled.div`
    position: absolute;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, .3);
    z-index: -1;
    visibility: ${props => props.display ? 'visible' : 'hidden'};
`;

export default class MobileReports extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isShowingDarkBackGround: true
        };
        this.handleCardContentTabClick = this.handleCardContentTabClick.bind(this);
        this.handlePlayerTabClick = this.handlePlayerTabClick.bind(this);
    }

    componentWillMount() {
        this.props.handleIsOpeningActivePage(true);
        this.props.handleShouldReportUpdate(true);
    }

    componentWillUnmount() {
        this.props.handleIsOpeningActivePage(false);
    }

    handleCardContentTabClick() {
        this.setState({
            isShowingDarkBackGround: true
        });
    }

    handlePlayerTabClick() {
        this.setState({
            isShowingDarkBackGround: false
        });
    }

    render() {
        const {
            currentLudoReportData,
            currentUserId,
            handleDenounceBoxOpen,
            handleShouldReportUpdate,
            params,
            router_currentFormValue,
            userBasicData
        } = this.props;
        const {
            comments_nick,
            introduction,
            player_id,
            starter_id,
            tags,
            title
        } = router_currentFormValue;
        return (

                <DarkBackGround
                    display={this.state.isShowingDarkBackGround}
                />
                <Tabs defaultIndex={1}>
                    <TabList className="react-tabs__tab-list mobile-avatar">
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handlePlayerTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <Avatar
                                avatarBackgroundColorIndex={comments_nick[starter_id][1]}
                                avatarImageIndex={comments_nick[starter_id][0]}
                                isThisBelongToCurrentUser={router_currentFormValue.starter_id == currentUserId}
                                userPhotoUrl={userPhotoUrl}
                            />
                        </Tab>
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handleCardContentTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <CardContentTab>
                                卡片內容
                            </CardContentTab>
                        </Tab>
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handlePlayerTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <Avatar
                                avatarBackgroundColorIndex={comments_nick[player_id][1]}
                                avatarImageIndex={comments_nick[player_id][0]}
                                isThisBelongToCurrentUser={router_currentFormValue.player_id == currentUserId}
                                userPhotoUrl={userPhotoUrl}
                            />
                        </Tab>
                    </TabList>

                    <TabPanel>
                        <ReportList
                            currentUserId={currentUserId}
                            handleDenounceBoxOpen={handleDenounceBoxOpen}
                            handleShouldReportUpdate={handleShouldReportUpdate}
                            isThisBelongToCurrentUser={router_currentFormValue.starter_id == currentUserId}
                            reportList={currentLudoReportData.filter(reportObject => reportObject.user_id == router_currentFormValue.starter_id)}
                            router_currentFormValue={router_currentFormValue}
                            userBasicData={userBasicData}
                        />
                        {router_currentFormValue.starter_id == currentUserId
                            ?
                                <ReportButton
                                    label="我要回報！"
                                    url={`/ludo/${params.ludo_id}/mobile-report-form`}
                                />
                            : null
                        }
                    </TabPanel>
                    <TabPanel>
                        <CardContent
                            introduction={introduction}
                            interval={router_currentFormValue.interval ? router_currentFormValue.interval : 1}
                            tags={tags}
                            title={title}
                        />
                    </TabPanel>
                    <TabPanel>
                        <ReportList
                            currentUserId={currentUserId}
                            handleDenounceBoxOpen={handleDenounceBoxOpen}
                            handleShouldReportUpdate={handleShouldReportUpdate}
                            isThisBelongToCurrentUser={router_currentFormValue.player_id == currentUserId}
                            reportList={currentLudoReportData.filter(reportObject => reportObject.user_id == router_currentFormValue.player_id)}
                            router_currentFormValue={router_currentFormValue}
                            userBasicData={userBasicData}
                        />
                        {router_currentFormValue.player_id == currentUserId
                            ?
                                <ReportButton
                                    label="我要回報！"
                                    url={`/ludo/${params.ludo_id}/mobile-report-form`}
                                />
                            : null
                        }
                    </TabPanel>
                </Tabs>

        );
    }
}

MobileReports.propTypes = {
    currentLudoReportData: PropTypes.arrayOf(
        PropTypes.shape({
            CreatedAt: PropTypes.string.isRequired,
            UpdatedAt: PropTypes.string.isRequired,
            image_location: PropTypes.string,
            ludo_id: PropTypes.string.isRequired,
            report_id: PropTypes.string.isRequired,
            tags: PropTypes.arrayOf(PropTypes.string),
            user_id: PropTypes.string.isRequired
        })
    ).isRequired,
    currentUserId: PropTypes.string.isRequired,
    handleDenounceBoxOpen: PropTypes.func.isRequired,
    handleIsOpeningActivePage: PropTypes.func.isRequired,
    handleShouldReportUpdate: PropTypes.func.isRequired,
    params: PropTypes.shape({
        ludo_id: PropTypes.string
    }).isRequired,
    router_currentFormValue: PropTypes.object.isRequired,
    userBasicData: PropTypes.object.isRequired
};

MobileReports.defaultProps = {
    'router_currentFormValue': {
        'comments_nick': {
            'a': [0, 0],
            'b': [0, 0]
        },
        'player_id': 'a',
        'starter_id': 'b'
    }
};
<commit_msg>modify mobile dark background position<commit_after>import React, { Component, PropTypes } from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import styled from 'styled-components';

import Avatar from '../components/Avatar';
import CardContent from '../components/CardContent';
import ReportButton from './ReportButton';
import ReportList from './ReportList';
import ReportText from './ReportText';

const userPhotoUrl = '../../images/animals/bat.png';

const CardContentTab = styled.div`
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    font-size: 0.8rem;
`;

const DarkBackGround = styled.div`
    position: fixed;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, .3);
    z-index: -1;
    visibility: ${props => props.display ? 'visible' : 'hidden'};
`;

export default class MobileReports extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isShowingDarkBackGround: true
        };
        this.handleCardContentTabClick = this.handleCardContentTabClick.bind(this);
        this.handlePlayerTabClick = this.handlePlayerTabClick.bind(this);
    }

    componentWillMount() {
        this.props.handleIsOpeningActivePage(true);
        this.props.handleShouldReportUpdate(true);
    }

    componentWillUnmount() {
        this.props.handleIsOpeningActivePage(false);
    }

    handleCardContentTabClick() {
        this.setState({
            isShowingDarkBackGround: true
        });
    }

    handlePlayerTabClick() {
        this.setState({
            isShowingDarkBackGround: false
        });
    }

    render() {
        const {
            currentLudoReportData,
            currentUserId,
            handleDenounceBoxOpen,
            handleShouldReportUpdate,
            params,
            router_currentFormValue,
            userBasicData
        } = this.props;
        const {
            comments_nick,
            introduction,
            player_id,
            starter_id,
            tags,
            title
        } = router_currentFormValue;
        return (

                <DarkBackGround
                    display={this.state.isShowingDarkBackGround}
                />
                <Tabs defaultIndex={1}>
                    <TabList className="react-tabs__tab-list mobile-avatar">
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handlePlayerTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <Avatar
                                avatarBackgroundColorIndex={comments_nick[starter_id][1]}
                                avatarImageIndex={comments_nick[starter_id][0]}
                                isThisBelongToCurrentUser={router_currentFormValue.starter_id == currentUserId}
                                userPhotoUrl={userPhotoUrl}
                            />
                        </Tab>
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handleCardContentTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <CardContentTab>
                                卡片內容
                            </CardContentTab>
                        </Tab>
                        <Tab
                            className="react-tabs__tab mobile-avatar"
                            onClick={this.handlePlayerTabClick}
                            selectedClassName="react-tabs__tab--selected mobile-avatar"
                        >
                            <Avatar
                                avatarBackgroundColorIndex={comments_nick[player_id][1]}
                                avatarImageIndex={comments_nick[player_id][0]}
                                isThisBelongToCurrentUser={router_currentFormValue.player_id == currentUserId}
                                userPhotoUrl={userPhotoUrl}
                            />
                        </Tab>
                    </TabList>

                    <TabPanel>
                        <ReportList
                            currentUserId={currentUserId}
                            handleDenounceBoxOpen={handleDenounceBoxOpen}
                            handleShouldReportUpdate={handleShouldReportUpdate}
                            isThisBelongToCurrentUser={router_currentFormValue.starter_id == currentUserId}
                            reportList={currentLudoReportData.filter(reportObject => reportObject.user_id == router_currentFormValue.starter_id)}
                            router_currentFormValue={router_currentFormValue}
                            userBasicData={userBasicData}
                        />
                        {router_currentFormValue.starter_id == currentUserId
                            ?
                                <ReportButton
                                    label="我要回報！"
                                    url={`/ludo/${params.ludo_id}/mobile-report-form`}
                                />
                            : null
                        }
                    </TabPanel>
                    <TabPanel>
                        <CardContent
                            introduction={introduction}
                            interval={router_currentFormValue.interval ? router_currentFormValue.interval : 1}
                            tags={tags}
                            title={title}
                        />
                    </TabPanel>
                    <TabPanel>
                        <ReportList
                            currentUserId={currentUserId}
                            handleDenounceBoxOpen={handleDenounceBoxOpen}
                            handleShouldReportUpdate={handleShouldReportUpdate}
                            isThisBelongToCurrentUser={router_currentFormValue.player_id == currentUserId}
                            reportList={currentLudoReportData.filter(reportObject => reportObject.user_id == router_currentFormValue.player_id)}
                            router_currentFormValue={router_currentFormValue}
                            userBasicData={userBasicData}
                        />
                        {router_currentFormValue.player_id == currentUserId
                            ?
                                <ReportButton
                                    label="我要回報！"
                                    url={`/ludo/${params.ludo_id}/mobile-report-form`}
                                />
                            : null
                        }
                    </TabPanel>
                </Tabs>

        );
    }
}

MobileReports.propTypes = {
    currentLudoReportData: PropTypes.arrayOf(
        PropTypes.shape({
            CreatedAt: PropTypes.string.isRequired,
            UpdatedAt: PropTypes.string.isRequired,
            image_location: PropTypes.string,
            ludo_id: PropTypes.string.isRequired,
            report_id: PropTypes.string.isRequired,
            tags: PropTypes.arrayOf(PropTypes.string),
            user_id: PropTypes.string.isRequired
        })
    ).isRequired,
    currentUserId: PropTypes.string.isRequired,
    handleDenounceBoxOpen: PropTypes.func.isRequired,
    handleIsOpeningActivePage: PropTypes.func.isRequired,
    handleShouldReportUpdate: PropTypes.func.isRequired,
    params: PropTypes.shape({
        ludo_id: PropTypes.string
    }).isRequired,
    router_currentFormValue: PropTypes.object.isRequired,
    userBasicData: PropTypes.object.isRequired
};

MobileReports.defaultProps = {
    'router_currentFormValue': {
        'comments_nick': {
            'a': [0, 0],
            'b': [0, 0]
        },
        'player_id': 'a',
        'starter_id': 'b'
    }
};
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('cr.ui', function() {

  /**
   * Returns the TabBox for a Tab or a TabPanel.
   * @param {Tab|TabPanel} el The tab or tabpanel element.
   * @return {TabBox} The tab box if found.
   */
  function getTabBox(el) {
    return el.parentElement && el.parentElement.parentElement;
  }

  /**
   * Set hook for the selected property for Tab and TabPanel.
   * This sets the selectedIndex on the parent TabBox.
   * @param {boolean} newValue The new selected value
   * @param {boolean} oldValue The old selected value. (This is ignored atm.)
   * @this {Tab|TabPanel}
   */
  function selectedSetHook(newValue, oldValue) {
    var tabBox;
    if (newValue && (tabBox = getTabBox(this)))
      tabBox.selectedIndex = Array.prototype.indexOf.call(p.children, this);
  }

  /**
   * Decorates all the children of an element.
   * @this {HTMLElement}
   */
  function decorateChildren() {
    var map = {
      TABBOX: TabBox,
      TABS: Tabs,
      TAB: Tab,
      TABPANELS: TabPanels,
      TABPANEL: TabPanel
    };

    var child;
    for (var i = 0; child = this.children[i]; i++) {
      var constr = map[child.tagName];
      if (constr)
        cr.ui.decorate(child, constr);
    }
  }

  /**
   * Set hook for TabBox selectedIndex.
   * @param {number} selectedIndex The new selected index.
   * @this {TabBox}
   */
  function selectedIndexSetHook(selectedIndex) {
    var child, tabChild;
    for (var i = 0; child = this.children[i]; i++) {
      for (var j = 0; tabChild = child.children[j]; j++) {
        tabChild.selected = j == selectedIndex;
      }
    }
  }

  /**
   * Creates a new tabbox element.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabBox = cr.ui.define('tabbox');

  TabBox.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      decorateChildren.call(this);
      this.addEventListener('selectedChange', this.handleSelectedChange_, true);
      this.selectedIndex = 0;
    },

    /**
     * Callback for when a Tab or TabPanel changes its selected property.
     * @param {Event} e The property change event.
     * @private
     */
    handleSelectedChange_: function(e) {
      var target = e.target;
      if (e.newValue && getTabBox(target) == this) {
        var index = Array.prototype.indexOf.call(target.parentElement.children,
                                                 target);
        this.selectedIndex = index;
      }
    },

    selectedIndex_: -1
  };

  /**
   * The index of the selected tab or -1 if no tab is selected.
   * @type {number}
   */
  cr.defineProperty(TabBox, 'selectedIndex', cr.PropertyKind.JS_PROP,
                    selectedIndexSetHook);

  /**
   * Creates a new tabs element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var Tabs = cr.ui.define('tabs');
  Tabs.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      decorateChildren.call(this);

      // Make the Tabs element fousable.
      this.tabIndex = 0;
      this.addEventListener('keydown', this.handleKeyDown_.bind(this));

      // Get (and initializes a focus outline manager.
      this.focusOutlineManager_ =
          cr.ui.FocusOutlineManager.forDocument(this.ownerDocument);
    },

    /**
     * Handle keydown to change the selected tab when the user presses the
     * arrow keys.
     * @param {Event} e The keyboard event.
     * @private
     */
    handleKeyDown_: function(e) {
      var delta = 0;
      switch (e.keyIdentifier) {
        case 'Left':
        case 'Up':
          delta = -1;
          break;
        case 'Right':
        case 'Down':
          delta = 1;
          break;
      }

      if (!delta)
        return;

      var cs = this.ownerDocument.defaultView.getComputedStyle(this);
      if (cs.direction == 'rtl')
        delta *= -1;

      var count = this.children.length;
      var index = this.parentElement.selectedIndex;
      this.parentElement.selectedIndex = (index + delta + count) % count;

      // Show focus outline since we used the keyboard.
      this.focusOutlineManager_.visible = true;
    }
  };

  /**
   * Creates a new tab element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var Tab = cr.ui.define('tab');
  Tab.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      var self = this;
      this.addEventListener(cr.isMac ? 'click' : 'mousedown', function() {
        self.selected = true;
      });
    }
  };

  /**
   * Whether the tab is selected.
   * @type {boolean}
   */
  cr.defineProperty(Tab, 'selected', cr.PropertyKind.BOOL_ATTR);

  /**
   * Creates a new tabpanels element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabPanels = cr.ui.define('tabpanels');
  TabPanels.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: decorateChildren
  };

  /**
   * Creates a new tabpanel element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabPanel = cr.ui.define('tabpanel');
  TabPanel.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {}
  };

  /**
   * Whether the tab is selected.
   * @type {boolean}
   */
  cr.defineProperty(TabPanel, 'selected', cr.PropertyKind.BOOL_ATTR);

  return {
    TabBox: TabBox,
    Tabs: Tabs,
    Tab: Tab,
    TabPanels: TabPanels,
    TabPanel: TabPanel
  };
});
<commit_msg>Add the documentation from the WebUI tabs commit to its fileoverview.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview This implements a tabbox and related element.
 *
 * Usage:
 *  <tabbox>
 *    <tabs>
 *      <tab>Hello</tab>
 *      <tab>World</tab>
 *    </tabs>
 *    <tabpanels>
 *      <tabpanel>Hi</tabpanel>
 *      <tabpanel>Tellus</tabpanel>
 *    </tabpanels>
 *  </tabbox>
 *
 *  <script>
 *  cr.ui.decorate('tabbox', cr.ui.TabBox);
 *  </script>
 *
 *  The tab and tabpanel elements have a selected property and the tabbox have a
 *  selectedIndex property reflecting the selected tab.
 */
cr.define('cr.ui', function() {

  /**
   * Returns the TabBox for a Tab or a TabPanel.
   * @param {Tab|TabPanel} el The tab or tabpanel element.
   * @return {TabBox} The tab box if found.
   */
  function getTabBox(el) {
    return el.parentElement && el.parentElement.parentElement;
  }

  /**
   * Set hook for the selected property for Tab and TabPanel.
   * This sets the selectedIndex on the parent TabBox.
   * @param {boolean} newValue The new selected value
   * @param {boolean} oldValue The old selected value. (This is ignored atm.)
   * @this {Tab|TabPanel}
   */
  function selectedSetHook(newValue, oldValue) {
    var tabBox;
    if (newValue && (tabBox = getTabBox(this)))
      tabBox.selectedIndex = Array.prototype.indexOf.call(p.children, this);
  }

  /**
   * Decorates all the children of an element.
   * @this {HTMLElement}
   */
  function decorateChildren() {
    var map = {
      TABBOX: TabBox,
      TABS: Tabs,
      TAB: Tab,
      TABPANELS: TabPanels,
      TABPANEL: TabPanel
    };

    var child;
    for (var i = 0; child = this.children[i]; i++) {
      var constr = map[child.tagName];
      if (constr)
        cr.ui.decorate(child, constr);
    }
  }

  /**
   * Set hook for TabBox selectedIndex.
   * @param {number} selectedIndex The new selected index.
   * @this {TabBox}
   */
  function selectedIndexSetHook(selectedIndex) {
    var child, tabChild;
    for (var i = 0; child = this.children[i]; i++) {
      for (var j = 0; tabChild = child.children[j]; j++) {
        tabChild.selected = j == selectedIndex;
      }
    }
  }

  /**
   * Creates a new tabbox element.
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabBox = cr.ui.define('tabbox');

  TabBox.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      decorateChildren.call(this);
      this.addEventListener('selectedChange', this.handleSelectedChange_, true);
      this.selectedIndex = 0;
    },

    /**
     * Callback for when a Tab or TabPanel changes its selected property.
     * @param {Event} e The property change event.
     * @private
     */
    handleSelectedChange_: function(e) {
      var target = e.target;
      if (e.newValue && getTabBox(target) == this) {
        var index = Array.prototype.indexOf.call(target.parentElement.children,
                                                 target);
        this.selectedIndex = index;
      }
    },

    selectedIndex_: -1
  };

  /**
   * The index of the selected tab or -1 if no tab is selected.
   * @type {number}
   */
  cr.defineProperty(TabBox, 'selectedIndex', cr.PropertyKind.JS_PROP,
                    selectedIndexSetHook);

  /**
   * Creates a new tabs element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var Tabs = cr.ui.define('tabs');
  Tabs.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      decorateChildren.call(this);

      // Make the Tabs element fousable.
      this.tabIndex = 0;
      this.addEventListener('keydown', this.handleKeyDown_.bind(this));

      // Get (and initializes a focus outline manager.
      this.focusOutlineManager_ =
          cr.ui.FocusOutlineManager.forDocument(this.ownerDocument);
    },

    /**
     * Handle keydown to change the selected tab when the user presses the
     * arrow keys.
     * @param {Event} e The keyboard event.
     * @private
     */
    handleKeyDown_: function(e) {
      var delta = 0;
      switch (e.keyIdentifier) {
        case 'Left':
        case 'Up':
          delta = -1;
          break;
        case 'Right':
        case 'Down':
          delta = 1;
          break;
      }

      if (!delta)
        return;

      var cs = this.ownerDocument.defaultView.getComputedStyle(this);
      if (cs.direction == 'rtl')
        delta *= -1;

      var count = this.children.length;
      var index = this.parentElement.selectedIndex;
      this.parentElement.selectedIndex = (index + delta + count) % count;

      // Show focus outline since we used the keyboard.
      this.focusOutlineManager_.visible = true;
    }
  };

  /**
   * Creates a new tab element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var Tab = cr.ui.define('tab');
  Tab.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {
      var self = this;
      this.addEventListener(cr.isMac ? 'click' : 'mousedown', function() {
        self.selected = true;
      });
    }
  };

  /**
   * Whether the tab is selected.
   * @type {boolean}
   */
  cr.defineProperty(Tab, 'selected', cr.PropertyKind.BOOL_ATTR);

  /**
   * Creates a new tabpanels element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabPanels = cr.ui.define('tabpanels');
  TabPanels.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: decorateChildren
  };

  /**
   * Creates a new tabpanel element.
   * @param {string} opt_label The text label for the item.
   * @constructor
   * @extends {HTMLElement}
   */
  var TabPanel = cr.ui.define('tabpanel');
  TabPanel.prototype = {
    __proto__: HTMLElement.prototype,
    decorate: function() {}
  };

  /**
   * Whether the tab is selected.
   * @type {boolean}
   */
  cr.defineProperty(TabPanel, 'selected', cr.PropertyKind.BOOL_ATTR);

  return {
    TabBox: TabBox,
    Tabs: Tabs,
    Tab: Tab,
    TabPanels: TabPanels,
    TabPanel: TabPanel
  };
});
<|endoftext|>


<commit_before>"use strict";
const should = require("should");
const sinon = require("sinon");
const UglifyJSPlugin = require("../lib/optimize/UglifyJSPlugin");
const PluginEnvironment = require("./helpers/PluginEnvironment");
const SourceMapSource = require("webpack-sources").SourceMapSource;
const RawSource = require("webpack-sources").RawSource;

describe("UglifyJSPlugin", function() {
	it("has apply function", function() {
		(new UglifyJSPlugin()).apply.should.be.a.Function();
	});

	describe("when applied with no options", function() {
		let eventBindings;
		let eventBinding;

		beforeEach(function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJSPlugin();
			plugin.apply(compilerEnv);
			eventBindings = pluginEnvironment.getEventBindings();
		});

		it("binds one event handler", function() {
			eventBindings.length.should.be.exactly(1);
		});

		describe("compilation handler", function() {
			beforeEach(function() {
				eventBinding = eventBindings[0];
			});

			it("binds to compilation event", function() {
				eventBinding.name.should.be.exactly("compilation");
			});

			describe("when called", function() {
				let chunkPluginEnvironment;
				let compilationEventBindings;
				let compilationEventBinding;
				let compilation;
				let callback;

				beforeEach(function() {
					chunkPluginEnvironment = new PluginEnvironment();
					compilation = chunkPluginEnvironment.getEnvironmentStub();
					compilation.assets = {
						"test.js": {
							__UglifyJsPlugin: {}
						},
						"test1.js": "",
						"test2.js": {
							source: function() {
								return "invalid javascript";
							}
						},
						"test3.js": {
							source: function() {
								return "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }";
							}
						}
					};
					compilation.errors = [];

					eventBinding.handler(compilation);
					compilationEventBindings = chunkPluginEnvironment.getEventBindings();
				});

				it("binds one event handler", function() {
					compilationEventBindings.length.should.be.exactly(1);
				});

				describe("optimize-chunk-assets handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[0];
					});

					it("binds to optimize-chunk-assets event", function() {
						compilationEventBinding.name.should.be.exactly("optimize-chunk-assets");
					});

					it("only calls callback once", function() {
						callback = sinon.spy();
						compilationEventBinding.handler([""], callback);
						callback.callCount.should.be.exactly(1);
					});

					it("default only parses filenames ending with .js", function() {
						compilationEventBinding.handler([{
							files: ["test", "test.js"]
						}], function() {
							Object.keys(compilation.assets).length.should.be.exactly(4);
						});
					});

					it("early returns if private property is already set", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"].should.deepEqual({});
						});
					});

					it("outputs stack trace errors for invalid asset", function() {
						compilationEventBinding.handler([{
							files: ["test1.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.have.containEql("TypeError");
						});
					});

					it("outputs parsing errors for invalid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test2.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.have.containEql("SyntaxError");
							compilation.errors[0].message.should.have.containEql("[test2.js:1,8]");
						});
					});

					it("outputs no errors for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
						});
					});

					it("outputs RawSource for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"].should.be.instanceof(RawSource);
						});
					});

					it("outputs mangled javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.not.containEql("longVariableName");
						});
					});

					it("compresses and does not output beautified javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.not.containEql("\n");
						});
					});

					it("preserves comments", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.containEql("/**");
						});
					});
				});
			});
		});
	});

	describe("when applied with invalid options", function() {
		it("outputs uglify errors", function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJSPlugin({
				output: {
					"invalid-option": true
				}
			});
			plugin.apply(compilerEnv);
			const eventBinding = pluginEnvironment.getEventBindings()[0];

			const chunkPluginEnvironment = new PluginEnvironment();
			const compilation = chunkPluginEnvironment.getEnvironmentStub();
			compilation.assets = {
				"test.js": {
					source: function() {
						return "var foo = 1;";
					}
				}
			};
			compilation.errors = [];

			eventBinding.handler(compilation);
			const compilationEventBinding = chunkPluginEnvironment.getEventBindings()[0];

			compilationEventBinding.handler([{
				files: ["test.js"]
			}], function() {
				compilation.errors.length.should.be.exactly(1);
				compilation.errors[0].message.should.have.containEql("supported option");
			});
		});
	});

	describe("when applied with all options", function() {
		let eventBindings;
		let eventBinding;

		beforeEach(function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJSPlugin({
				sourceMap: true,
				compress: {
					warnings: true,
				},
				mangle: false,
				beautify: true,
				comments: false
			});
			plugin.apply(compilerEnv);
			eventBindings = pluginEnvironment.getEventBindings();
		});

		it("binds one event handler", function() {
			eventBindings.length.should.be.exactly(1);
		});

		describe("compilation handler", function() {
			beforeEach(function() {
				eventBinding = eventBindings[0];
			});

			it("binds to compilation event", function() {
				eventBinding.name.should.be.exactly("compilation");
			});

			describe("when called", function() {
				let chunkPluginEnvironment;
				let compilationEventBindings;
				let compilationEventBinding;
				let compilation;

				beforeEach(function() {
					chunkPluginEnvironment = new PluginEnvironment();
					compilation = chunkPluginEnvironment.getEnvironmentStub();
					compilation.assets = {
						"test.js": {
							source: function() {
								return "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test.js"],
									names: ["foo", "longVariableName"],
									mappings: "AAAA,QAASA,KAAIC,kBACTA,iBAAmB"
								};
							}
						},
						"test1.js": {
							source: function() {
								return "invalid javascript";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test1.js"],
									names: [""],
									mappings: "AAAA"
								};
							}
						},
						"test2.js": {
							source: function() {
								return "function foo(x) { if (x) { return bar(); not_called1(); } }";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test1.js"],
									names: ["foo", "x", "bar", "not_called1"],
									mappings: "AAAA,QAASA,KAAIC,GACT,GAAIA,EAAG,CACH,MAAOC,MACPC"
								};
							}
						},
						"test3.js": {
							sourceAndMap: function() {
								return {
									source: "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }",
									map: {
										version: 3,
										sources: ["test.js"],
										names: ["foo", "longVariableName"],
										mappings: "AAAA,QAASA,KAAIC,kBACTA,iBAAmB"
									}
								};
							},
						},
					};
					compilation.errors = [];
					compilation.warnings = [];

					eventBinding.handler(compilation);
					compilationEventBindings = chunkPluginEnvironment.getEventBindings();
				});

				it("binds two event handler", function() {
					compilationEventBindings.length.should.be.exactly(2);
				});

				describe("build-module handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[0];
					});

					it("binds to build-module event", function() {
						compilationEventBinding.name.should.be.exactly("build-module");
					});

					it("sets the useSourceMap flag", function() {
						const obj = {};
						compilationEventBinding.handler(obj);
						obj.useSourceMap.should.be.equal(true);
					});
				});

				describe("optimize-chunk-assets handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[1];
					});

					it("binds to optimize-chunk-assets event", function() {
						compilationEventBinding.name.should.be.exactly("optimize-chunk-assets");
					});

					it("outputs no errors for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
						});
					});

					it("outputs SourceMapSource for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"].should.be.instanceof(SourceMapSource);
						});
					});

					it("does not output mangled javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.containEql("longVariableName");
						});
					});

					it("outputs beautified javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.containEql("\n");
						});
					});

					it("does not preserve comments", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.not.containEql("/**");
						});
					});

					it("outputs parsing errors", function() {
						compilationEventBinding.handler([{
							files: ["test1.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.containEql("[test1.js:1,0][test1.js:1,8]");
						});
					});

					it("outputs warnings for unreachable code", function() {
						compilationEventBinding.handler([{
							files: ["test2.js"]
						}], function() {
							compilation.warnings.length.should.be.exactly(1);
							compilation.warnings[0].should.be.an.Error;
							compilation.warnings[0].message.should.containEql("Dropping unreachable code");
						});
					});

					it("works with sourceAndMap assets as well", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
							compilation.assets["test3.js"].should.be.instanceof(SourceMapSource);
						});
					});
				});
			});
		});
	});
});
<commit_msg>Fix naming<commit_after>"use strict";
const should = require("should");
const sinon = require("sinon");
const UglifyJsPlugin = require("../lib/optimize/UglifyJsPlugin");
const PluginEnvironment = require("./helpers/PluginEnvironment");
const SourceMapSource = require("webpack-sources").SourceMapSource;
const RawSource = require("webpack-sources").RawSource;

describe("UglifyJsPlugin", function() {
	it("has apply function", function() {
		(new UglifyJsPlugin()).apply.should.be.a.Function();
	});

	describe("when applied with no options", function() {
		let eventBindings;
		let eventBinding;

		beforeEach(function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJsPlugin();
			plugin.apply(compilerEnv);
			eventBindings = pluginEnvironment.getEventBindings();
		});

		it("binds one event handler", function() {
			eventBindings.length.should.be.exactly(1);
		});

		describe("compilation handler", function() {
			beforeEach(function() {
				eventBinding = eventBindings[0];
			});

			it("binds to compilation event", function() {
				eventBinding.name.should.be.exactly("compilation");
			});

			describe("when called", function() {
				let chunkPluginEnvironment;
				let compilationEventBindings;
				let compilationEventBinding;
				let compilation;
				let callback;

				beforeEach(function() {
					chunkPluginEnvironment = new PluginEnvironment();
					compilation = chunkPluginEnvironment.getEnvironmentStub();
					compilation.assets = {
						"test.js": {
							__UglifyJsPlugin: {}
						},
						"test1.js": "",
						"test2.js": {
							source: function() {
								return "invalid javascript";
							}
						},
						"test3.js": {
							source: function() {
								return "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }";
							}
						}
					};
					compilation.errors = [];

					eventBinding.handler(compilation);
					compilationEventBindings = chunkPluginEnvironment.getEventBindings();
				});

				it("binds one event handler", function() {
					compilationEventBindings.length.should.be.exactly(1);
				});

				describe("optimize-chunk-assets handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[0];
					});

					it("binds to optimize-chunk-assets event", function() {
						compilationEventBinding.name.should.be.exactly("optimize-chunk-assets");
					});

					it("only calls callback once", function() {
						callback = sinon.spy();
						compilationEventBinding.handler([""], callback);
						callback.callCount.should.be.exactly(1);
					});

					it("default only parses filenames ending with .js", function() {
						compilationEventBinding.handler([{
							files: ["test", "test.js"]
						}], function() {
							Object.keys(compilation.assets).length.should.be.exactly(4);
						});
					});

					it("early returns if private property is already set", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"].should.deepEqual({});
						});
					});

					it("outputs stack trace errors for invalid asset", function() {
						compilationEventBinding.handler([{
							files: ["test1.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.have.containEql("TypeError");
						});
					});

					it("outputs parsing errors for invalid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test2.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.have.containEql("SyntaxError");
							compilation.errors[0].message.should.have.containEql("[test2.js:1,8]");
						});
					});

					it("outputs no errors for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
						});
					});

					it("outputs RawSource for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"].should.be.instanceof(RawSource);
						});
					});

					it("outputs mangled javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.not.containEql("longVariableName");
						});
					});

					it("compresses and does not output beautified javascript", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.not.containEql("\n");
						});
					});

					it("preserves comments", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.assets["test3.js"]._value.should.containEql("/**");
						});
					});
				});
			});
		});
	});

	describe("when applied with invalid options", function() {
		it("outputs uglify errors", function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJsPlugin({
				output: {
					"invalid-option": true
				}
			});
			plugin.apply(compilerEnv);
			const eventBinding = pluginEnvironment.getEventBindings()[0];

			const chunkPluginEnvironment = new PluginEnvironment();
			const compilation = chunkPluginEnvironment.getEnvironmentStub();
			compilation.assets = {
				"test.js": {
					source: function() {
						return "var foo = 1;";
					}
				}
			};
			compilation.errors = [];

			eventBinding.handler(compilation);
			const compilationEventBinding = chunkPluginEnvironment.getEventBindings()[0];

			compilationEventBinding.handler([{
				files: ["test.js"]
			}], function() {
				compilation.errors.length.should.be.exactly(1);
				compilation.errors[0].message.should.have.containEql("supported option");
			});
		});
	});

	describe("when applied with all options", function() {
		let eventBindings;
		let eventBinding;

		beforeEach(function() {
			const pluginEnvironment = new PluginEnvironment();
			const compilerEnv = pluginEnvironment.getEnvironmentStub();
			compilerEnv.context = "";

			const plugin = new UglifyJsPlugin({
				sourceMap: true,
				compress: {
					warnings: true,
				},
				mangle: false,
				beautify: true,
				comments: false
			});
			plugin.apply(compilerEnv);
			eventBindings = pluginEnvironment.getEventBindings();
		});

		it("binds one event handler", function() {
			eventBindings.length.should.be.exactly(1);
		});

		describe("compilation handler", function() {
			beforeEach(function() {
				eventBinding = eventBindings[0];
			});

			it("binds to compilation event", function() {
				eventBinding.name.should.be.exactly("compilation");
			});

			describe("when called", function() {
				let chunkPluginEnvironment;
				let compilationEventBindings;
				let compilationEventBinding;
				let compilation;

				beforeEach(function() {
					chunkPluginEnvironment = new PluginEnvironment();
					compilation = chunkPluginEnvironment.getEnvironmentStub();
					compilation.assets = {
						"test.js": {
							source: function() {
								return "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test.js"],
									names: ["foo", "longVariableName"],
									mappings: "AAAA,QAASA,KAAIC,kBACTA,iBAAmB"
								};
							}
						},
						"test1.js": {
							source: function() {
								return "invalid javascript";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test1.js"],
									names: [""],
									mappings: "AAAA"
								};
							}
						},
						"test2.js": {
							source: function() {
								return "function foo(x) { if (x) { return bar(); not_called1(); } }";
							},
							map: function() {
								return {
									version: 3,
									sources: ["test1.js"],
									names: ["foo", "x", "bar", "not_called1"],
									mappings: "AAAA,QAASA,KAAIC,GACT,GAAIA,EAAG,CACH,MAAOC,MACPC"
								};
							}
						},
						"test3.js": {
							sourceAndMap: function() {
								return {
									source: "/** @preserve Foo Bar */ function foo(longVariableName) { longVariableName = 1; }",
									map: {
										version: 3,
										sources: ["test.js"],
										names: ["foo", "longVariableName"],
										mappings: "AAAA,QAASA,KAAIC,kBACTA,iBAAmB"
									}
								};
							},
						},
					};
					compilation.errors = [];
					compilation.warnings = [];

					eventBinding.handler(compilation);
					compilationEventBindings = chunkPluginEnvironment.getEventBindings();
				});

				it("binds two event handler", function() {
					compilationEventBindings.length.should.be.exactly(2);
				});

				describe("build-module handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[0];
					});

					it("binds to build-module event", function() {
						compilationEventBinding.name.should.be.exactly("build-module");
					});

					it("sets the useSourceMap flag", function() {
						const obj = {};
						compilationEventBinding.handler(obj);
						obj.useSourceMap.should.be.equal(true);
					});
				});

				describe("optimize-chunk-assets handler", function() {
					beforeEach(function() {
						compilationEventBinding = compilationEventBindings[1];
					});

					it("binds to optimize-chunk-assets event", function() {
						compilationEventBinding.name.should.be.exactly("optimize-chunk-assets");
					});

					it("outputs no errors for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
						});
					});

					it("outputs SourceMapSource for valid javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"].should.be.instanceof(SourceMapSource);
						});
					});

					it("does not output mangled javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.containEql("longVariableName");
						});
					});

					it("outputs beautified javascript", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.containEql("\n");
						});
					});

					it("does not preserve comments", function() {
						compilationEventBinding.handler([{
							files: ["test.js"]
						}], function() {
							compilation.assets["test.js"]._value.should.not.containEql("/**");
						});
					});

					it("outputs parsing errors", function() {
						compilationEventBinding.handler([{
							files: ["test1.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(1);
							compilation.errors[0].should.be.an.Error;
							compilation.errors[0].message.should.containEql("[test1.js:1,0][test1.js:1,8]");
						});
					});

					it("outputs warnings for unreachable code", function() {
						compilationEventBinding.handler([{
							files: ["test2.js"]
						}], function() {
							compilation.warnings.length.should.be.exactly(1);
							compilation.warnings[0].should.be.an.Error;
							compilation.warnings[0].message.should.containEql("Dropping unreachable code");
						});
					});

					it("works with sourceAndMap assets as well", function() {
						compilationEventBinding.handler([{
							files: ["test3.js"]
						}], function() {
							compilation.errors.length.should.be.exactly(0);
							compilation.assets["test3.js"].should.be.instanceof(SourceMapSource);
						});
					});
				});
			});
		});
	});
});
<|endoftext|>