<commit_before>import Shevy from '../src'

describe('Shevy', () => {
  it('is defined', () => {
    const shevy = new Shevy()
    expect(shevy).toBeDefined()
  })

  describe('Defined Properties', () => {
    const shevy = new Shevy()
    const {
      baseFontSize,
      baseFontUnit,
      baseLineHeight,
      baseFontScale,
      addMarginBottom,
      proximity,
      proximityFactor,
      lineHeightSpacing,
      baseSpacing,
      body,
      content
    } = shevy

    it('baseFontSize', () => { expect(baseFontSize).toBeDefined() })
    it('baseFontUnit', () => { expect(baseFontUnit).toBeDefined() })
    it('baseLineHeight', () => { expect(baseLineHeight).toBeDefined() })
    it('baseFontScale', () => { expect(baseFontScale).toBeDefined() })
    it('addMarginBottom', () => { expect(addMarginBottom).toBeDefined() })
    it('addMarginBottom', () => { expect(addMarginBottom).toBeDefined() })
    it('proximity', () => { expect(proximity).toBeDefined() })
    it('proximityFactor', () => { expect(proximityFactor).toBeDefined() })
    it('body', () => { expect(body).toBeDefined() })
    it('content', () => { expect(content).toBeDefined() })
    it('lineHeightSpacing', () => { expect(lineHeightSpacing).toBeDefined() })
    it('baseSpacing', () => { expect(baseSpacing).toBeDefined() })
  })

  describe('Default settings', () => {
    const shevy = new Shevy()

    describe('Property Values', () => {
      it('baseFontSize is 16px', () => {
        expect(shevy.baseFontSize).toEqual('16px')
      })

      it('baseFontUnit is px', () => {
        expect(shevy.baseFontUnit).toEqual('px')
      })

      it('baseLineHeight is 1.5', () => {
        expect(shevy.baseLineHeight).toEqual(1.5)
      })

      it('baseFontScale is an array of default values', () => {
        const expectedScale = [3, 2.5, 2, 1.5, 1.25, 1]
        expect(shevy.baseFontScale).toEqual(expectedScale)
      })

      it('addMarginBottom is true', () => {
        expect(shevy.addMarginBottom).toEqual(true)
      })

      it('proximity is false', () => {
        expect(shevy.proximity).toEqual(false)
      })

      it('proximityFactor is .85', () => {
        expect(shevy.proximityFactor).toEqual(.85)
      })
    })

    describe('Headings', () => {
      const { h1, h2, h3, h4, h5, h6 } = shevy

      describe('h1', () => {
        it('fontSize is 48px', () => { expect(h1.fontSize).toEqual('48px') })
        it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
        it('marginBottom is 24px', () => { expect(h1.marginBottom).toEqual('24px') })
      })

      describe('h2', () => {
        it('fontSize is 40px', () => { expect(h2.fontSize).toEqual('40px') })
        it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
        it('marginBottom is 24px', () => { expect(h2.marginBottom).toEqual('24px') })
      })

      describe('h3', () => {
        it('fontSize is 32px', () => { expect(h3.fontSize).toEqual('32px') })
        it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
        it('marginBottom is 24px', () => { expect(h3.marginBottom).toEqual('24px') })
      })

      describe('h4', () => {
        it('fontSize is 24px', () => { expect(h4.fontSize).toEqual('24px') })
        it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
        it('marginBottom is 24px', () => { expect(h4.marginBottom).toEqual('24px') })
      })

      describe('h5', () => {
        it('fontSize is 20px', () => { expect(h5.fontSize).toEqual('20px') })
        it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
        it('marginBottom is 24px', () => { expect(h5.marginBottom).toEqual('24px') })
      })

      describe('h6', () => {
        it('fontSize is 16px', () => { expect(h6.fontSize).toEqual('16px') })
        it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
        it('marginBottom is 24px', () => { expect(h6.marginBottom).toEqual('24px') })
      })
    })

    describe('Body', () => {
      const { body } = shevy

      it('fontSize is 16px', () => {
        expect(body.fontSize).toEqual('16px')
      })

      it('lineHeight of 1.5', () => {
        expect(body.lineHeight).toEqual(1.5)
      })
    })

    describe('Content', () => {
      const { content } = shevy

      it('fontSize is 16px', () => {
        expect(content.fontSize).toEqual('16px')
      })

      it('lineHeight is 1.5', () => {
        expect(content.lineHeight).toEqual(1.5)
      })

      it('marginBottom is 24px', () => {
        expect(content.marginBottom).toEqual('24px')
      })
    })

    describe('Methods', () => {
      it('lineHeightSpacing returns 24px', () => {
        expect(shevy.lineHeightSpacing()).toEqual('24px')
      })

      it('baseSpacing returns 24px', () => {
        expect(shevy.baseSpacing()).toEqual('24px')
      })
    })
  })

  describe('Custom settings', () => {
    describe('unit: em', () => {
      const shevy = new Shevy({
        baseFontSize: '1em'
      })

      describe('Property Values', () => {
        it('baseFontSize is 1em', () => {
          expect(shevy.baseFontSize).toEqual('1em')
        })

        it('baseFontUnit is em', () => {
          expect(shevy.baseFontUnit).toEqual('em')
        })
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('fontSize is 3em', () => { expect(h1.fontSize).toEqual('3em') })
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 0.5em', () => { expect(h1.marginBottom).toEqual('0.5em') })
        })

        describe('h2', () => {
          it('fontSize is 2.5em', () => { expect(h2.fontSize).toEqual('2.5em') })
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 0.6em', () => { expect(h2.marginBottom).toEqual('0.6em') })
        })

        describe('h3', () => {
          it('fontSize is 2em', () => { expect(h3.fontSize).toEqual('2em') })
          it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
          it('marginBottom is 0.75em', () => { expect(h3.marginBottom).toEqual('0.75em') })
        })

        describe('h4', () => {
          it('fontSize is 1.5em', () => { expect(h4.fontSize).toEqual('1.5em') })
          it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
          it('marginBottom is 1em', () => { expect(h4.marginBottom).toEqual('1em') })
        })

        describe('h5', () => {
          it('fontSize is 1.25em', () => { expect(h5.fontSize).toEqual('1.25em') })
          it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.2em', () => { expect(h5.marginBottom).toEqual('1.2em') })
        })

        describe('h6', () => {
          it('fontSize is 1em', () => { expect(h6.fontSize).toEqual('1em') })
          it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
          it('marginBottom is 1.5em', () => { expect(h6.marginBottom).toEqual('1.5em') })
        })
      })

      describe('Body', () => {
        const { body } = shevy

        it('fontSize is 1em', () => {
          expect(body.fontSize).toEqual('1em')
        })
      })

      describe('Content', () => {
        const { content } = shevy

        it('fontSize is 1em', () => {
          expect(content.fontSize).toEqual('1em')
        })
      })

      describe('Methods', () => {
        it('lineHeightSpacing returns 1.5em', () => {
          expect(shevy.lineHeightSpacing()).toEqual('1.5em')
        })

        it('baseSpacing returns 1.5em', () => {
          expect(shevy.baseSpacing()).toEqual('1.5em')
        })
      })
    })

    describe('unit: rem', () => {
      const shevy = new Shevy({
        baseFontSize: '1rem'
      })

      describe('Property Values', () => {
        it('baseFontSize is 1rem', () => {
          expect(shevy.baseFontSize).toEqual('1rem')
        })

        it('baseFontUnit is rem', () => {
          expect(shevy.baseFontUnit).toEqual('rem')
        })
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('fontSize is 3rem', () => { expect(h1.fontSize).toEqual('3rem') })
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 1.5rem', () => { expect(h1.marginBottom).toEqual('1.5rem') })
        })

        describe('h2', () => {
          it('fontSize is 2.5rem', () => { expect(h2.fontSize).toEqual('2.5rem') })
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.5rem', () => { expect(h2.marginBottom).toEqual('1.5rem') })
        })

        describe('h3', () => {
          it('fontSize is 2rem', () => { expect(h3.fontSize).toEqual('2rem') })
          it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
          it('marginBottom is 1.5rem', () => { expect(h3.marginBottom).toEqual('1.5rem') })
        })

        describe('h4', () => {
          it('fontSize is 1.5rem', () => { expect(h4.fontSize).toEqual('1.5rem') })
          it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
          it('marginBottom is 1.5rem', () => { expect(h4.marginBottom).toEqual('1.5rem') })
        })

        describe('h5', () => {
          it('fontSize is 1.25rem', () => { expect(h5.fontSize).toEqual('1.25rem') })
          it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.5rem', () => { expect(h5.marginBottom).toEqual('1.5rem') })
        })

        describe('h6', () => {
          it('fontSize is 1rem', () => { expect(h6.fontSize).toEqual('1rem') })
          it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
          it('marginBottom is 1.5rem', () => { expect(h6.marginBottom).toEqual('1.5rem') })
        })
      })

      describe('Body', () => {
        const { body } = shevy

        it('fontSize is 1rem', () => {
          expect(body.fontSize).toEqual('1rem')
        })
      })

      describe('Content', () => {
        const { content } = shevy

        it('fontSize is 1rem', () => {
          expect(content.fontSize).toEqual('1rem')
        })
      })

      describe('Methods', () => {
        it('lineHeightSpacing returns 1.5rem', () => {
          expect(shevy.lineHeightSpacing()).toEqual('1.5rem')
        })

        it('baseSpacing returns 1.5rem', () => {
          expect(shevy.baseSpacing()).toEqual('1.5rem')
        })
      })
    })

    describe('baseLineHeight: 2', () => {
      const shevy = new Shevy({
        baseLineHeight: 2
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 32px', () => { expect(h1.marginBottom).toEqual('32px') })
        })

        describe('h2', () => {
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 32px', () => { expect(h2.marginBottom).toEqual('32px') })
        })

        describe('h3', () => {
          it('lineHeight is 1', () => { expect(h3.lineHeight).toEqual(1) })
          it('marginBottom is 32px', () => { expect(h3.marginBottom).toEqual('32px') })
        })

        describe('h4', () => {
          it('lineHeight is 1.3333333333333333', () => {
            expect(h4.lineHeight).toEqual(1.3333333333333333)
          })
          it('marginBottom is 32px', () => { expect(h4.marginBottom).toEqual('32px') })
        })

        describe('h5', () => {
          it('lineHeight is 1.6', () => { expect(h5.lineHeight).toEqual(1.6) })
          it('marginBottom is 32px', () => { expect(h5.marginBottom).toEqual('32px') })
        })

        describe('h6', () => {
          it('lineHeight is 2', () => { expect(h6.lineHeight).toEqual(2) })
          it('marginBottom is 32px', () => { expect(h6.marginBottom).toEqual('32px') })
        })
      })
    })

    describe('baseFontScale', () => {
      describe('has length < 6', () => {
        const shevy = new Shevy({
          baseFontScale: [3, 2, 1]
        })

        describe('Undefined Headings', () => {
          const { h4, h5, h6 } = shevy

          it('h4 should be undefined', () => { expect(h4).not.toBeDefined() })
          it('h5 should be undefined', () => { expect(h5).not.toBeDefined() })
          it('h6 should be undefined', () => { expect(h6).not.toBeDefined() })
        })
      })

      describe('has length > 6', () => {
        const shevy = new Shevy({
          baseFontScale: [7, 6, 5, 4, 3, 2, 1]
        })

        it('should trim array to length of 6, removing from the end', () => {
          const expectedArray = [7, 6, 5, 4, 3, 2]
          expect(shevy.baseFontScale).toEqual(expectedArray)
        })
      })
    })
  })
})
<commit_msg>add tests for when marginBottom is false<commit_after>import Shevy from '../src'

describe('Shevy', () => {
  it('is defined', () => {
    const shevy = new Shevy()
    expect(shevy).toBeDefined()
  })

  describe('Defined Properties', () => {
    const shevy = new Shevy()
    const {
      baseFontSize,
      baseFontUnit,
      baseLineHeight,
      baseFontScale,
      addMarginBottom,
      proximity,
      proximityFactor,
      lineHeightSpacing,
      baseSpacing,
      body,
      content
    } = shevy

    it('baseFontSize', () => { expect(baseFontSize).toBeDefined() })
    it('baseFontUnit', () => { expect(baseFontUnit).toBeDefined() })
    it('baseLineHeight', () => { expect(baseLineHeight).toBeDefined() })
    it('baseFontScale', () => { expect(baseFontScale).toBeDefined() })
    it('addMarginBottom', () => { expect(addMarginBottom).toBeDefined() })
    it('addMarginBottom', () => { expect(addMarginBottom).toBeDefined() })
    it('proximity', () => { expect(proximity).toBeDefined() })
    it('proximityFactor', () => { expect(proximityFactor).toBeDefined() })
    it('body', () => { expect(body).toBeDefined() })
    it('content', () => { expect(content).toBeDefined() })
    it('lineHeightSpacing', () => { expect(lineHeightSpacing).toBeDefined() })
    it('baseSpacing', () => { expect(baseSpacing).toBeDefined() })
  })

  describe('Default settings', () => {
    const shevy = new Shevy()

    describe('Property Values', () => {
      it('baseFontSize is 16px', () => {
        expect(shevy.baseFontSize).toEqual('16px')
      })

      it('baseFontUnit is px', () => {
        expect(shevy.baseFontUnit).toEqual('px')
      })

      it('baseLineHeight is 1.5', () => {
        expect(shevy.baseLineHeight).toEqual(1.5)
      })

      it('baseFontScale is an array of default values', () => {
        const expectedScale = [3, 2.5, 2, 1.5, 1.25, 1]
        expect(shevy.baseFontScale).toEqual(expectedScale)
      })

      it('addMarginBottom is true', () => {
        expect(shevy.addMarginBottom).toEqual(true)
      })

      it('proximity is false', () => {
        expect(shevy.proximity).toEqual(false)
      })

      it('proximityFactor is .85', () => {
        expect(shevy.proximityFactor).toEqual(.85)
      })
    })

    describe('Headings', () => {
      const { h1, h2, h3, h4, h5, h6 } = shevy

      describe('h1', () => {
        it('fontSize is 48px', () => { expect(h1.fontSize).toEqual('48px') })
        it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
        it('marginBottom is 24px', () => { expect(h1.marginBottom).toEqual('24px') })
      })

      describe('h2', () => {
        it('fontSize is 40px', () => { expect(h2.fontSize).toEqual('40px') })
        it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
        it('marginBottom is 24px', () => { expect(h2.marginBottom).toEqual('24px') })
      })

      describe('h3', () => {
        it('fontSize is 32px', () => { expect(h3.fontSize).toEqual('32px') })
        it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
        it('marginBottom is 24px', () => { expect(h3.marginBottom).toEqual('24px') })
      })

      describe('h4', () => {
        it('fontSize is 24px', () => { expect(h4.fontSize).toEqual('24px') })
        it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
        it('marginBottom is 24px', () => { expect(h4.marginBottom).toEqual('24px') })
      })

      describe('h5', () => {
        it('fontSize is 20px', () => { expect(h5.fontSize).toEqual('20px') })
        it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
        it('marginBottom is 24px', () => { expect(h5.marginBottom).toEqual('24px') })
      })

      describe('h6', () => {
        it('fontSize is 16px', () => { expect(h6.fontSize).toEqual('16px') })
        it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
        it('marginBottom is 24px', () => { expect(h6.marginBottom).toEqual('24px') })
      })
    })

    describe('Body', () => {
      const { body } = shevy

      it('fontSize is 16px', () => {
        expect(body.fontSize).toEqual('16px')
      })

      it('lineHeight of 1.5', () => {
        expect(body.lineHeight).toEqual(1.5)
      })
    })

    describe('Content', () => {
      const { content } = shevy

      it('fontSize is 16px', () => {
        expect(content.fontSize).toEqual('16px')
      })

      it('lineHeight is 1.5', () => {
        expect(content.lineHeight).toEqual(1.5)
      })

      it('marginBottom is 24px', () => {
        expect(content.marginBottom).toEqual('24px')
      })
    })

    describe('Methods', () => {
      it('lineHeightSpacing returns 24px', () => {
        expect(shevy.lineHeightSpacing()).toEqual('24px')
      })

      it('baseSpacing returns 24px', () => {
        expect(shevy.baseSpacing()).toEqual('24px')
      })
    })
  })

  describe('Custom settings', () => {
    describe('unit: em', () => {
      const shevy = new Shevy({
        baseFontSize: '1em'
      })

      describe('Property Values', () => {
        it('baseFontSize is 1em', () => {
          expect(shevy.baseFontSize).toEqual('1em')
        })

        it('baseFontUnit is em', () => {
          expect(shevy.baseFontUnit).toEqual('em')
        })
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('fontSize is 3em', () => { expect(h1.fontSize).toEqual('3em') })
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 0.5em', () => { expect(h1.marginBottom).toEqual('0.5em') })
        })

        describe('h2', () => {
          it('fontSize is 2.5em', () => { expect(h2.fontSize).toEqual('2.5em') })
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 0.6em', () => { expect(h2.marginBottom).toEqual('0.6em') })
        })

        describe('h3', () => {
          it('fontSize is 2em', () => { expect(h3.fontSize).toEqual('2em') })
          it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
          it('marginBottom is 0.75em', () => { expect(h3.marginBottom).toEqual('0.75em') })
        })

        describe('h4', () => {
          it('fontSize is 1.5em', () => { expect(h4.fontSize).toEqual('1.5em') })
          it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
          it('marginBottom is 1em', () => { expect(h4.marginBottom).toEqual('1em') })
        })

        describe('h5', () => {
          it('fontSize is 1.25em', () => { expect(h5.fontSize).toEqual('1.25em') })
          it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.2em', () => { expect(h5.marginBottom).toEqual('1.2em') })
        })

        describe('h6', () => {
          it('fontSize is 1em', () => { expect(h6.fontSize).toEqual('1em') })
          it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
          it('marginBottom is 1.5em', () => { expect(h6.marginBottom).toEqual('1.5em') })
        })
      })

      describe('Body', () => {
        const { body } = shevy

        it('fontSize is 1em', () => {
          expect(body.fontSize).toEqual('1em')
        })
      })

      describe('Content', () => {
        const { content } = shevy

        it('fontSize is 1em', () => {
          expect(content.fontSize).toEqual('1em')
        })
      })

      describe('Methods', () => {
        it('lineHeightSpacing returns 1.5em', () => {
          expect(shevy.lineHeightSpacing()).toEqual('1.5em')
        })

        it('baseSpacing returns 1.5em', () => {
          expect(shevy.baseSpacing()).toEqual('1.5em')
        })
      })
    })

    describe('unit: rem', () => {
      const shevy = new Shevy({
        baseFontSize: '1rem'
      })

      describe('Property Values', () => {
        it('baseFontSize is 1rem', () => {
          expect(shevy.baseFontSize).toEqual('1rem')
        })

        it('baseFontUnit is rem', () => {
          expect(shevy.baseFontUnit).toEqual('rem')
        })
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('fontSize is 3rem', () => { expect(h1.fontSize).toEqual('3rem') })
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 1.5rem', () => { expect(h1.marginBottom).toEqual('1.5rem') })
        })

        describe('h2', () => {
          it('fontSize is 2.5rem', () => { expect(h2.fontSize).toEqual('2.5rem') })
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.5rem', () => { expect(h2.marginBottom).toEqual('1.5rem') })
        })

        describe('h3', () => {
          it('fontSize is 2rem', () => { expect(h3.fontSize).toEqual('2rem') })
          it('lineHeight is 1.125', () => { expect(h3.lineHeight).toEqual(1.125) })
          it('marginBottom is 1.5rem', () => { expect(h3.marginBottom).toEqual('1.5rem') })
        })

        describe('h4', () => {
          it('fontSize is 1.5rem', () => { expect(h4.fontSize).toEqual('1.5rem') })
          it('lineHeight is 1', () => { expect(h4.lineHeight).toEqual(1) })
          it('marginBottom is 1.5rem', () => { expect(h4.marginBottom).toEqual('1.5rem') })
        })

        describe('h5', () => {
          it('fontSize is 1.25rem', () => { expect(h5.fontSize).toEqual('1.25rem') })
          it('lineHeight is 1.2', () => { expect(h5.lineHeight).toEqual(1.2) })
          it('marginBottom is 1.5rem', () => { expect(h5.marginBottom).toEqual('1.5rem') })
        })

        describe('h6', () => {
          it('fontSize is 1rem', () => { expect(h6.fontSize).toEqual('1rem') })
          it('lineHeight is 1.5', () => { expect(h6.lineHeight).toEqual(1.5) })
          it('marginBottom is 1.5rem', () => { expect(h6.marginBottom).toEqual('1.5rem') })
        })
      })

      describe('Body', () => {
        const { body } = shevy

        it('fontSize is 1rem', () => {
          expect(body.fontSize).toEqual('1rem')
        })
      })

      describe('Content', () => {
        const { content } = shevy

        it('fontSize is 1rem', () => {
          expect(content.fontSize).toEqual('1rem')
        })
      })

      describe('Methods', () => {
        it('lineHeightSpacing returns 1.5rem', () => {
          expect(shevy.lineHeightSpacing()).toEqual('1.5rem')
        })

        it('baseSpacing returns 1.5rem', () => {
          expect(shevy.baseSpacing()).toEqual('1.5rem')
        })
      })
    })

    describe('baseLineHeight: 2', () => {
      const shevy = new Shevy({
        baseLineHeight: 2
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        describe('h1', () => {
          it('lineHeight is 1', () => { expect(h1.lineHeight).toEqual(1) })
          it('marginBottom is 32px', () => { expect(h1.marginBottom).toEqual('32px') })
        })

        describe('h2', () => {
          it('lineHeight is 1.2', () => { expect(h2.lineHeight).toEqual(1.2) })
          it('marginBottom is 32px', () => { expect(h2.marginBottom).toEqual('32px') })
        })

        describe('h3', () => {
          it('lineHeight is 1', () => { expect(h3.lineHeight).toEqual(1) })
          it('marginBottom is 32px', () => { expect(h3.marginBottom).toEqual('32px') })
        })

        describe('h4', () => {
          it('lineHeight is 1.3333333333333333', () => {
            expect(h4.lineHeight).toEqual(1.3333333333333333)
          })
          it('marginBottom is 32px', () => { expect(h4.marginBottom).toEqual('32px') })
        })

        describe('h5', () => {
          it('lineHeight is 1.6', () => { expect(h5.lineHeight).toEqual(1.6) })
          it('marginBottom is 32px', () => { expect(h5.marginBottom).toEqual('32px') })
        })

        describe('h6', () => {
          it('lineHeight is 2', () => { expect(h6.lineHeight).toEqual(2) })
          it('marginBottom is 32px', () => { expect(h6.marginBottom).toEqual('32px') })
        })
      })
    })

    describe('baseFontScale', () => {
      describe('has length < 6', () => {
        const shevy = new Shevy({
          baseFontScale: [3, 2, 1]
        })

        describe('Undefined Headings', () => {
          const { h4, h5, h6 } = shevy

          it('h4 should be undefined', () => { expect(h4).not.toBeDefined() })
          it('h5 should be undefined', () => { expect(h5).not.toBeDefined() })
          it('h6 should be undefined', () => { expect(h6).not.toBeDefined() })
        })
      })

      describe('has length > 6', () => {
        const shevy = new Shevy({
          baseFontScale: [7, 6, 5, 4, 3, 2, 1]
        })

        it('should trim array to length of 6, removing from the end', () => {
          const expectedArray = [7, 6, 5, 4, 3, 2]
          expect(shevy.baseFontScale).toEqual(expectedArray)
        })
      })
    })

    describe('addMarginBottom: false', () => {
      const shevy = new Shevy({
        addMarginBottom: false
      })

      describe('Headings', () => {
        const { h1, h2, h3, h4, h5, h6 } = shevy

        it('marginBottoms should be undefined', () => {
          expect(h1.marginBottom).not.toBeDefined()
          expect(h2.marginBottom).not.toBeDefined()
          expect(h3.marginBottom).not.toBeDefined()
          expect(h4.marginBottom).not.toBeDefined()
          expect(h5.marginBottom).not.toBeDefined()
          expect(h6.marginBottom).not.toBeDefined()
        })
      })

      describe('Content', () => {
        const { content } = shevy

        it('marginBottom should be undefined', () => {
          expect(content.marginBottom).not.toBeDefined()
        })
      })
    })
  })
})
<|endoftext|>


<commit_before>const NativeModules = require('react-native').NativeModules
const NativeClient = NativeModules.BugsnagReactNative

const REMOTE_DEBUGGING_WARNING = `Bugsnag cannot initialise synchronously when running in the remote debugger.

Error reporting is still supported, but synchronous calls afted Bugsnag.start() will no-op. This means Bugsnag.leaveBreadcrumb(), Bugsnag.setUser() and all other methods will only begin to work after a short delay.

This only affects the remote debugger. Execution of JS in the normal way (on the device) is not affected.`

const isDebuggingRemotely = !global.nativeCallSyncHook

const name = 'Bugsnag React Native'
const { version } = require('../package.json')
const url = 'https://github.com/bugsnag/bugsnag-js'

const React = require('react')

const Client = require('@bugsnag/core/client')
const Event = require('@bugsnag/core/event')
const Session = require('@bugsnag/core/session')
const Breadcrumb = require('@bugsnag/core/breadcrumb')

const delivery = require('@bugsnag/delivery-react-native')

const BugsnagPluginReact = require('@bugsnag/plugin-react')

const { schema, load, loadAsync } = require('./config')

const internalPlugins = [
  require('@bugsnag/plugin-react-native-session')(NativeClient),
  require('@bugsnag/plugin-react-native-event-sync')(NativeClient),
  require('@bugsnag/plugin-react-native-client-sync')(NativeClient),
  require('@bugsnag/plugin-react-native-global-error-handler')(),
  require('@bugsnag/plugin-react-native-unhandled-rejection'),
  require('@bugsnag/plugin-console-breadcrumbs'),
  require('@bugsnag/plugin-network-breadcrumbs')(),
  new BugsnagPluginReact(React)
]

const CLIENT_METHODS = Object.getOwnPropertyNames(Client.prototype)

const createClientAsync = async (jsOpts) => {
  const opts = await loadAsync(NativeClient, version)
  return _createClient(opts, jsOpts)
}

const createClient = (jsOpts) => {
  const opts = load(NativeClient, version)
  return _createClient(opts, jsOpts)
}

const _createClient = (opts, jsOpts) => {
  if (jsOpts && typeof jsOpts === 'object') {
    // mutate the options with anything supplied in JS. This will throw
    Object.keys(jsOpts).forEach(k => { opts[k] = jsOpts[k] })
  }

  const bugsnag = new Client(opts, schema, internalPlugins, { name, version, url })

  bugsnag._setDelivery(client => delivery(client, NativeClient))

  if (opts.user && opts.user !== opts._originalValues.user) {
    bugsnag.setUser(opts.user.id, opts.user.email, opts.user.name)
  }

  if (opts.context && opts.context !== opts._originalValues.context) {
    bugsnag.setContext(opts.context)
  }

  if (opts.metadata && opts.metadata !== opts._originalValues.metadata) {
    Object.keys(opts.metadata).forEach(k => bugsnag.addMetadata(k, opts.metadata[k]))
  }

  if (opts.codeBundleId) {
    NativeClient.updateCodeBundleId(opts.codeBundleId)
  }

  bugsnag._logger.debug('Loaded!')

  return bugsnag
}

const Bugsnag = {
  _client: null,
  start: (opts) => {
    if (Bugsnag._client) {
      Bugsnag._client._logger.warn('Bugsnag.start() was called more than once. Ignoring.')
      return Bugsnag._client
    }
    if (!isDebuggingRemotely) {
      Bugsnag._client = createClient(opts)
      Bugsnag._client._depth += 1
      return Bugsnag._client
    } else {
      console.warn(REMOTE_DEBUGGING_WARNING)
      let initialised = false
      const stubClient = {}
      CLIENT_METHODS.reduce((accum, m) => {
        stubClient[m] = new Proxy(() => {
          console.warn(`Bugsnag.${m}() will no-op because Bugsnag has not yet initialised`)
        }, {
          apply: (target, thisArg, argumentsList) => {
            if (!initialised) return Reflect.apply(target, thisArg, argumentsList)
            return Reflect.apply(Bugsnag._client[m], Bugsnag._client, argumentsList)
          }
        })
      })
      Bugsnag._client = stubClient
      createClientAsync(opts).then(client => {
        initialised = true
        Bugsnag._client = client
        Bugsnag._client._depth += 1
      })
      return stubClient
    }
  }
}

CLIENT_METHODS.map((m) => {
  if (/^_/.test(m)) return
  Bugsnag[m] = function () {
    if (!Bugsnag._client) return console.warn(`Bugsnag.${m}() was called before Bugsnag.start()`)
    return Bugsnag._client[m].apply(Bugsnag._client, arguments)
  }
})

module.exports = Bugsnag

module.exports.Client = Client
module.exports.Event = Event
module.exports.Session = Session
module.exports.Breadcrumb = Breadcrumb

// Export a "default" property for compatibility with ESM imports
module.exports.default = Bugsnag
<commit_msg>style(react-native): Update comments and log messages<commit_after>const NativeModules = require('react-native').NativeModules
const NativeClient = NativeModules.BugsnagReactNative

const REMOTE_DEBUGGING_WARNING = `Bugsnag cannot initialize synchronously when running in the remote debugger.

Error reporting is still supported, but synchronous calls afted Bugsnag.start() will no-op. This means Bugsnag.leaveBreadcrumb(), Bugsnag.setUser() and all other methods will only begin to work after a short delay.

This only affects the remote debugger. Execution of JS in the normal way (on the device) is not affected.`

// this is how some internal react native code detects whether the app is running
// in the remote debugger:
//   https://github.com/facebook/react-native/blob/1f4535c17572df78e2a033890220337e5703b614/Libraries/ReactNative/PaperUIManager.js#L62-L66
// there's no public api for this so we use the same approach
const isDebuggingRemotely = !global.nativeCallSyncHook

const name = 'Bugsnag React Native'
const { version } = require('../package.json')
const url = 'https://github.com/bugsnag/bugsnag-js'

const React = require('react')

const Client = require('@bugsnag/core/client')
const Event = require('@bugsnag/core/event')
const Session = require('@bugsnag/core/session')
const Breadcrumb = require('@bugsnag/core/breadcrumb')

const delivery = require('@bugsnag/delivery-react-native')

const BugsnagPluginReact = require('@bugsnag/plugin-react')

const { schema, load, loadAsync } = require('./config')

const internalPlugins = [
  require('@bugsnag/plugin-react-native-session')(NativeClient),
  require('@bugsnag/plugin-react-native-event-sync')(NativeClient),
  require('@bugsnag/plugin-react-native-client-sync')(NativeClient),
  require('@bugsnag/plugin-react-native-global-error-handler')(),
  require('@bugsnag/plugin-react-native-unhandled-rejection'),
  require('@bugsnag/plugin-console-breadcrumbs'),
  require('@bugsnag/plugin-network-breadcrumbs')(),
  new BugsnagPluginReact(React)
]

const CLIENT_METHODS = Object.getOwnPropertyNames(Client.prototype)

const createClientAsync = async (jsOpts) => {
  const opts = await loadAsync(NativeClient, version)
  return _createClient(opts, jsOpts)
}

const createClient = (jsOpts) => {
  const opts = load(NativeClient, version)
  return _createClient(opts, jsOpts)
}

const _createClient = (opts, jsOpts) => {
  if (jsOpts && typeof jsOpts === 'object') {
    // mutate the options with anything supplied in JS. This will throw
    Object.keys(jsOpts).forEach(k => { opts[k] = jsOpts[k] })
  }

  const bugsnag = new Client(opts, schema, internalPlugins, { name, version, url })

  bugsnag._setDelivery(client => delivery(client, NativeClient))

  if (opts.user && opts.user !== opts._originalValues.user) {
    bugsnag.setUser(opts.user.id, opts.user.email, opts.user.name)
  }

  if (opts.context && opts.context !== opts._originalValues.context) {
    bugsnag.setContext(opts.context)
  }

  if (opts.metadata && opts.metadata !== opts._originalValues.metadata) {
    Object.keys(opts.metadata).forEach(k => bugsnag.addMetadata(k, opts.metadata[k]))
  }

  if (opts.codeBundleId) {
    NativeClient.updateCodeBundleId(opts.codeBundleId)
  }

  bugsnag._logger.debug('Loaded!')

  return bugsnag
}

const Bugsnag = {
  _client: null,
  start: (opts) => {
    if (Bugsnag._client) {
      Bugsnag._client._logger.warn('Bugsnag.start() was called more than once. Ignoring.')
      return Bugsnag._client
    }
    if (!isDebuggingRemotely) {
      Bugsnag._client = createClient(opts)
      Bugsnag._client._depth += 1
      return Bugsnag._client
    } else {
      console.warn(REMOTE_DEBUGGING_WARNING)
      let initialised = false
      const stubClient = {}
      CLIENT_METHODS.reduce((accum, m) => {
        stubClient[m] = new Proxy(() => {
          console.warn(
            `This call to Bugsnag.${m}() is a no-op because remote debugging is enabled and Bugsnag has not yet initialized`
          )
        }, {
          apply: (target, thisArg, argumentsList) => {
            if (!initialised) return Reflect.apply(target, thisArg, argumentsList)
            return Reflect.apply(Bugsnag._client[m], Bugsnag._client, argumentsList)
          }
        })
      })
      Bugsnag._client = stubClient
      createClientAsync(opts).then(client => {
        initialised = true
        Bugsnag._client = client
        Bugsnag._client._depth += 1
      })
      return stubClient
    }
  }
}

CLIENT_METHODS.map((m) => {
  if (/^_/.test(m)) return
  Bugsnag[m] = function () {
    if (!Bugsnag._client) return console.warn(`Bugsnag.${m}() was called before Bugsnag.start()`)
    return Bugsnag._client[m].apply(Bugsnag._client, arguments)
  }
})

module.exports = Bugsnag

module.exports.Client = Client
module.exports.Event = Event
module.exports.Session = Session
module.exports.Breadcrumb = Breadcrumb

// Export a "default" property for compatibility with ESM imports
module.exports.default = Bugsnag
<|endoftext|>


<commit_before>import React from 'react'
import { StyleSheet, css } from 'aphrodite'
import { omit, pickBy } from 'lodash'
import { applyNiceStyles, flattenThemes, isFunc, filterStyleKeys, filterParentStyleKeys } from './helpers'

const styleKey = 'motion$style'

const defaultOpts = {
  themes: true
}

module.exports = function motionStyle(opts = defaultOpts) {
  // helpers
  const getDynamicStyles = (active, props, styles, propPrefix = '$') => {
    const dynamicKeys = active.filter(k => styles[k] && typeof styles[k] === 'function')
    const dynamicsReduce = (acc, k) => ({ ...acc, [k]: styles[k](props[`${propPrefix}${k}`]) })
    const dynamics = dynamicKeys.reduce(dynamicsReduce, {})
    return dynamics
  }

  const getDynamicSheets = dynamics => {
    const sheet = StyleSheet.create(applyNiceStyles(dynamics))
    return Object.keys(dynamics).map(k => sheet[k])
  }

  const processStyles = (userStyles, theme) => {
    const styles = { ...userStyles, ...flattenThemes(theme) }
    const dynamics = pickBy(styles, isFunc)
    const statics = pickBy(styles, x => !isFunc(x))

    return {
      statics: StyleSheet.create(applyNiceStyles(statics)),
      dynamics,
      theme
    }
  }

  // decorator
  const decorator = (Child, parentStyles) => {
    if (!Child.style) return Child

    const styles = processStyles(Child.style, opts.themes ? Child.theme : null)

    return class StyledComponent extends Child {
      static displayName = Child.displayName || Child.name

      __styles = styles

      render() {
        return this.styleAll.call(this, super.render())
      }

      styleAll(children) {
        if (!children || !Array.isArray(children) && !children.props) return children

        const styler = this.styleOne.bind(this)
        if (Array.isArray(children)) {
          return children.map(styler)
        }

        const count = React.Children.count(children)
        if (count > 1) {
          return React.Children.map(children, styler)
        }

        return styler(children)
      }

      styleOne(child) {
        if (Array.isArray(child)) return this.styleAll(child)
        if (!child || !React.isValidElement(child)) return child

        // only style tags from within current view
        if (child.props[styleKey] !== this[styleKey]) return child

        // <View /> + <tag /> keys
        const name = child.type && (child.type.name || child.type)

        // <name $one $two /> keys
        const propKeys = Object.keys(child.props)
        const styleKeys = filterStyleKeys(propKeys)

        // remove $
        const activeKeys = styleKeys
          .filter(key => child.props[key] !== false && typeof child.props[key] !== 'undefined')
          .map(key => key.slice(1))

        // tag + $props
        const allKeys = [name, ...activeKeys]
        let finalKeys = [...allKeys]

        // collect styles
        let finalStyles = []

        //
        // theme styles
        //
        if (opts.themes) {
          const themeKeys = prop => allKeys.map(k => `${prop}-${k}`)
          const addTheme = (keys, prop) => [...keys, ...themeKeys(prop)]

          // direct
          const themes = this.constructor.theme
          const themeProps = themes && Object.keys(themes)

          if (themes && themeProps.length) {
            console.log('themeProps', themeProps)
            themeProps.forEach(prop => {
              if (this.props[prop] === true) {
                // static theme
                finalKeys = addTheme(finalKeys, prop)
              } else if (
                typeof this.props[prop] !== 'undefined' &&
                styles.theme[prop]
              ) {
                // dynamic themes
                const dynStyles = getDynamicStyles([prop], this.props, styles.theme, '')[prop]

                if (dynStyles) {
                  finalStyles = [...finalStyles, ...getDynamicSheets(dynStyles)]
                }
              }
            })
          }
        }

        //
        // parent styles
        //
        let parentStyleKeys = []
        if (parentStyles) {
          parentStyleKeys = filterParentStyleKeys(propKeys)

          if (parentStyleKeys.length) {
            const keys = parentStyleKeys.map(k => k.replace('$$', ''))

            // dynamic
            if (parentStyles.dynamics) {
              finalStyles = [
                ...finalStyles,
                ...getDynamicSheets(getDynamicStyles(keys, child.props, parentStyles.dynamics, '$$'))
              ]
            }

            // static
            if (parentStyles.statics) {
              finalStyles = [
                ...finalStyles,
                ...keys.map(k => parentStyles.statics[k])
              ]
            }
          }
        }

        //
        // own styles
        //
        // static
        finalStyles = [...finalStyles, ...finalKeys.map(i => styles.statics[i])]
        // dynamic
        if (styles.dynamics && activeKeys.length) {
          finalStyles = [
            ...finalStyles,
            ...getDynamicSheets(getDynamicStyles(activeKeys, child.props, styles.dynamics))
          ]
        }

        // recreate child (without style props)
        const { key, ref, props, type } = child
        const newProps = omit(props, [...styleKeys, ...parentStyleKeys, 'motion$style'])
        if (ref) newProps.ref = ref
        if (key) newProps.key = key

        if (finalStyles.length) {
          // apply styles
          newProps.className = css(...finalStyles)

          // keep original classNames
          if (props && props.className && typeof props.className === 'string') {
            newProps.className += ` ${props.className}`
          }
        }

        // recurse to children
        if (newProps && newProps.children) {
          newProps.children = this.styleAll(child.props.children)
        }

        return React.createElement(type, newProps)
      }
    }
  }

  decorator.parent = styles => {
    const parentStyles = processStyles(styles)
    return Child => decorator(Child, parentStyles)
  }

  return decorator
}
<commit_msg>:fire: remove log<commit_after>import React from 'react'
import { StyleSheet, css } from 'aphrodite'
import { omit, pickBy } from 'lodash'
import { applyNiceStyles, flattenThemes, isFunc, filterStyleKeys, filterParentStyleKeys } from './helpers'

const styleKey = 'motion$style'

const defaultOpts = {
  themes: true
}

module.exports = function motionStyle(opts = defaultOpts) {
  // helpers
  const getDynamicStyles = (active, props, styles, propPrefix = '$') => {
    const dynamicKeys = active.filter(k => styles[k] && typeof styles[k] === 'function')
    const dynamicsReduce = (acc, k) => ({ ...acc, [k]: styles[k](props[`${propPrefix}${k}`]) })
    const dynamics = dynamicKeys.reduce(dynamicsReduce, {})
    return dynamics
  }

  const getDynamicSheets = dynamics => {
    const sheet = StyleSheet.create(applyNiceStyles(dynamics))
    return Object.keys(dynamics).map(k => sheet[k])
  }

  const processStyles = (userStyles, theme) => {
    const styles = { ...userStyles, ...flattenThemes(theme) }
    const dynamics = pickBy(styles, isFunc)
    const statics = pickBy(styles, x => !isFunc(x))

    return {
      statics: StyleSheet.create(applyNiceStyles(statics)),
      dynamics,
      theme
    }
  }

  // decorator
  const decorator = (Child, parentStyles) => {
    if (!Child.style) return Child

    const styles = processStyles(Child.style, opts.themes ? Child.theme : null)

    return class StyledComponent extends Child {
      static displayName = Child.displayName || Child.name

      __styles = styles

      render() {
        return this.styleAll.call(this, super.render())
      }

      styleAll(children) {
        if (!children || !Array.isArray(children) && !children.props) return children

        const styler = this.styleOne.bind(this)
        if (Array.isArray(children)) {
          return children.map(styler)
        }

        const count = React.Children.count(children)
        if (count > 1) {
          return React.Children.map(children, styler)
        }

        return styler(children)
      }

      styleOne(child) {
        if (Array.isArray(child)) return this.styleAll(child)
        if (!child || !React.isValidElement(child)) return child

        // only style tags from within current view
        if (child.props[styleKey] !== this[styleKey]) return child

        // <View /> + <tag /> keys
        const name = child.type && (child.type.name || child.type)

        // <name $one $two /> keys
        const propKeys = Object.keys(child.props)
        const styleKeys = filterStyleKeys(propKeys)

        // remove $
        const activeKeys = styleKeys
          .filter(key => child.props[key] !== false && typeof child.props[key] !== 'undefined')
          .map(key => key.slice(1))

        // tag + $props
        const allKeys = [name, ...activeKeys]
        let finalKeys = [...allKeys]

        // collect styles
        let finalStyles = []

        //
        // theme styles
        //
        if (opts.themes) {
          const themeKeys = prop => allKeys.map(k => `${prop}-${k}`)
          const addTheme = (keys, prop) => [...keys, ...themeKeys(prop)]

          // direct
          const themes = this.constructor.theme
          const themeProps = themes && Object.keys(themes)

          if (themes && themeProps.length) {
            themeProps.forEach(prop => {
              if (this.props[prop] === true) {
                // static theme
                finalKeys = addTheme(finalKeys, prop)
              } else if (
                typeof this.props[prop] !== 'undefined' &&
                styles.theme[prop]
              ) {
                // dynamic themes
                const dynStyles = getDynamicStyles([prop], this.props, styles.theme, '')[prop]

                if (dynStyles) {
                  finalStyles = [...finalStyles, ...getDynamicSheets(dynStyles)]
                }
              }
            })
          }
        }

        //
        // parent styles
        //
        let parentStyleKeys = []
        if (parentStyles) {
          parentStyleKeys = filterParentStyleKeys(propKeys)

          if (parentStyleKeys.length) {
            const keys = parentStyleKeys.map(k => k.replace('$$', ''))

            // dynamic
            if (parentStyles.dynamics) {
              finalStyles = [
                ...finalStyles,
                ...getDynamicSheets(getDynamicStyles(keys, child.props, parentStyles.dynamics, '$$'))
              ]
            }

            // static
            if (parentStyles.statics) {
              finalStyles = [
                ...finalStyles,
                ...keys.map(k => parentStyles.statics[k])
              ]
            }
          }
        }

        //
        // own styles
        //
        // static
        finalStyles = [...finalStyles, ...finalKeys.map(i => styles.statics[i])]
        // dynamic
        if (styles.dynamics && activeKeys.length) {
          finalStyles = [
            ...finalStyles,
            ...getDynamicSheets(getDynamicStyles(activeKeys, child.props, styles.dynamics))
          ]
        }

        // recreate child (without style props)
        const { key, ref, props, type } = child
        const newProps = omit(props, [...styleKeys, ...parentStyleKeys, 'motion$style'])
        if (ref) newProps.ref = ref
        if (key) newProps.key = key

        if (finalStyles.length) {
          // apply styles
          newProps.className = css(...finalStyles)

          // keep original classNames
          if (props && props.className && typeof props.className === 'string') {
            newProps.className += ` ${props.className}`
          }
        }

        // recurse to children
        if (newProps && newProps.children) {
          newProps.children = this.styleAll(child.props.children)
        }

        return React.createElement(type, newProps)
      }
    }
  }

  decorator.parent = styles => {
    const parentStyles = processStyles(styles)
    return Child => decorator(Child, parentStyles)
  }

  return decorator
}
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var logger = require('../../utils/logger');
var utils = require('./utils');
var appData = require('./app_data');

var getClosestModel = appData.getClosestModel = function(elem) {
  var model = null;
  var wrapper = utils.closest(elem, 'js-model-list-item');
  if (wrapper) {
    model = appData.models[wrapper.getAttribute('data-id')];
  }
  return model;
};

appData.updateSelectedModel = function() {
  if (typeof appData.selectedModel.obj.getPropertiesArray === 'function') {
    appData.selectedModel.modelProperties = appData.selectedModel.obj.getPropertiesArray();
  }
  utils.render();
};

module.exports = function() {
  utils.addEvent('js-toggle-model-children', 'click', function(e) {
    e.stopPropagation();
    var view = getClosestModel(e.target);
    view.collapsed = !view.collapsed;
    if (!view.collapsed) {
      appData.allModelsCollapsed = false;
    }
    utils.render();
  });
  utils.addEvent('js-collapse-all-models', 'click', function() {
    for (var model in appData.models) {
      model = appData.models[model];
      if (model.isParent()) {
        model.collapsed = !appData.allModelsCollapsed;
      }
    }
    appData.allModelsCollapsed = !appData.allModelsCollapsed;
    utils.render();
  });
  utils.addEvent('js-model-list-item', 'click', function(e) {
    appData.selectModel(getClosestModel(e.target));
  });
  utils.addEvent('js-more-model-info', 'click', function(e) {
    var model = getClosestModel(e.target).obj;
    logger.log(model);
  });
  utils.addEvent('js-derived-property', 'click', function(e) {
    var key = utils.closest(e.currentTarget, 'js-derived-property').getAttribute('data-key');
    var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.derived, {
      key: key
    });
    if (selectedProperty) {
      logger.log(key, selectedProperty.data.isDerived.deps, selectedProperty.data.isDerived.fn);
    }
  });
  utils.addEvent('js-model-property', 'click', function(e) {
    var key = utils.closest(e.currentTarget, 'js-model-property').getAttribute('data-key');
    var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.normal, {
      key: key
    });
    if (selectedProperty && !selectedProperty.data.isEditing) {
      selectedProperty.data.isEditing = true;
      utils.render();
      utils.selectElements('js-model-property-value')[0].focus();
    }
  });
  utils.addEvent('js-model-property-value', 'blur', function(e) {
    var key = utils.closest(e.currentTarget, 'js-model-property').getAttribute('data-key');
    try {
      var value = JSON.parse(e.currentTarget.value);
      var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.normal, {
        key: key
      });
      selectedProperty.data.isEditing = false;
      selectedProperty.data.value = value;
      appData.selectedModel.obj.set(key, value);
      appData.updateSelectedModel();
    } catch (ex) {
      var message = 'Unable to parse "' + e.currentTarget.value + '" to a valid value. Input must match JSON format';
      utils.alert(message);
      logger.warn(message);
      utils.selectElements('js-model-property-value')[0].focus();
    }
  });
  utils.addEvent('js-model-property-value', 'keyup', function(e) {
    var which = (e.which || e.keyCode);
    if (which === 13) {
      e.currentTarget.blur();
    }
  });
  utils.addEvent('js-track-function', 'click', function(e) {
    var fnName = e.currentTarget.getAttribute('data-fn');
    var selectedFunction = _.findWhere(appData.selectedModel.objectFunctions, {
      name: fnName
    });
    selectedFunction.tracked = !selectedFunction.tracked;
    appData.selectedModel.toggleFunctionTracking(fnName, selectedFunction.tracked);
    utils.render();
  });
  utils.addEvent('js-show-inherited', 'change', function(e) {
    e.stopPropagation();
    appData.settings.showInheritedMethods = e.currentTarget.checked;
    utils.render();
  });
  utils.addEvent('js-add-new-event', 'blur', function(e) {
    var eventName = e.currentTarget.value;
    if (/^\s*$/.test(eventName)) {
      return;
    }
    var existing = _.findWhere(appData.selectedModel.customEvents, {
      name: eventName
    });
    if (!existing) {
      var listener = utils.addListener(appData.selectedModel.obj, eventName);
      appData.selectedModel.customEvents.push({
        name: eventName,
        listener: listener
      });
    }
    utils.render();
  });
  utils.addEvent('js-add-new-event', 'keyup', function(e) {
    var which = (e.which || e.keyCode);
    if (which === 13) {
      e.currentTarget.blur();
    }
  });
  utils.addEvent('js-untrack-event', 'click', function(e) {
    var eventName = utils.closest(e.currentTarget, 'js-tracked-event').getAttribute('data-key');
    var events = appData.selectedModel.customEvents;
    for (var i = 0; i < events.length; i++) {
      if (events[i].name === eventName) {
        utils.removeListener(appData.selectedModel.obj, events[i].name, events[i].listener);
        events.splice(i, 1);
        break;
      }
    }
    utils.render();
  });
  utils.addEvent('js-get-model-data', 'click', function() {
    appData.selectedModel.outputData = JSON.stringify(appData.selectedModel.obj);
    utils.render();
  });
  utils.addEvent('js-set-model-data', 'click', function() {
    var textbox = utils.selectElements('js-model-data')[0];
    appData.selectedModel.outputData = '';
    appData.selectedModel.obj.reset(JSON.parse(textbox.value));
    appData.updateSelectedModel();
  });
  utils.addEvent('js-reset-data', 'click', function() {
    appData.selectedModel.obj.reset(appData.selectedModel.obj.initialData);
    appData.updateSelectedModel();
  });
  utils.addEvent('js-remove-attribute', 'click', function(e) {
    e.stopPropagation();
    appData.selectedModel.obj.unset(e.currentTarget.getAttribute('data-key'));
    appData.updateSelectedModel();
  });
  utils.addEvent('js-add-attribute', 'click', function() {
    appData.settings.modelProperties = appData.settings.modelProperties || {};
    appData.settings.modelProperties.adding = true;
    utils.render();
  });
  utils.addEvent('js-cancel-adding-attribute', 'click', function() {
    appData.settings.modelProperties = appData.settings.modelProperties || {};
    appData.settings.modelProperties.adding = false;
    utils.render();
  });
  utils.addEvent('js-adding-attribute', 'submit', function(e) {
    e.preventDefault();
    var form = e.currentTarget;
    var name = form.name.value;
    var value;
    try {
      value = JSON.parse(form.value.value);
    } catch (ex) {
      value = form.value.value;
    }
    var model = appData.selectedModel.obj;
    if (model.has(name)) {
      alert('Model already has property named "' + name + '"');
    } else {
      model.set(name, value);
      appData.settings.modelProperties = appData.settings.modelProperties || {};
      appData.settings.modelProperties.adding = false;
      appData.updateSelectedModel();
    }
  });
};
<commit_msg>change holdover variable name to match context<commit_after>'use strict';

var _ = require('underscore');
var logger = require('../../utils/logger');
var utils = require('./utils');
var appData = require('./app_data');

var getClosestModel = appData.getClosestModel = function(elem) {
  var model = null;
  var wrapper = utils.closest(elem, 'js-model-list-item');
  if (wrapper) {
    model = appData.models[wrapper.getAttribute('data-id')];
  }
  return model;
};

appData.updateSelectedModel = function() {
  if (typeof appData.selectedModel.obj.getPropertiesArray === 'function') {
    appData.selectedModel.modelProperties = appData.selectedModel.obj.getPropertiesArray();
  }
  utils.render();
};

module.exports = function() {
  utils.addEvent('js-toggle-model-children', 'click', function(e) {
    e.stopPropagation();
    var model = getClosestModel(e.target);
    model.collapsed = !model.collapsed;
    if (!model.collapsed) {
      appData.allModelsCollapsed = false;
    }
    utils.render();
  });
  utils.addEvent('js-collapse-all-models', 'click', function() {
    for (var model in appData.models) {
      model = appData.models[model];
      if (model.isParent()) {
        model.collapsed = !appData.allModelsCollapsed;
      }
    }
    appData.allModelsCollapsed = !appData.allModelsCollapsed;
    utils.render();
  });
  utils.addEvent('js-model-list-item', 'click', function(e) {
    appData.selectModel(getClosestModel(e.target));
  });
  utils.addEvent('js-more-model-info', 'click', function(e) {
    var model = getClosestModel(e.target).obj;
    logger.log(model);
  });
  utils.addEvent('js-derived-property', 'click', function(e) {
    var key = utils.closest(e.currentTarget, 'js-derived-property').getAttribute('data-key');
    var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.derived, {
      key: key
    });
    if (selectedProperty) {
      logger.log(key, selectedProperty.data.isDerived.deps, selectedProperty.data.isDerived.fn);
    }
  });
  utils.addEvent('js-model-property', 'click', function(e) {
    var key = utils.closest(e.currentTarget, 'js-model-property').getAttribute('data-key');
    var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.normal, {
      key: key
    });
    if (selectedProperty && !selectedProperty.data.isEditing) {
      selectedProperty.data.isEditing = true;
      utils.render();
      utils.selectElements('js-model-property-value')[0].focus();
    }
  });
  utils.addEvent('js-model-property-value', 'blur', function(e) {
    var key = utils.closest(e.currentTarget, 'js-model-property').getAttribute('data-key');
    try {
      var value = JSON.parse(e.currentTarget.value);
      var selectedProperty = _.findWhere(appData.selectedModel.modelProperties.normal, {
        key: key
      });
      selectedProperty.data.isEditing = false;
      selectedProperty.data.value = value;
      appData.selectedModel.obj.set(key, value);
      appData.updateSelectedModel();
    } catch (ex) {
      var message = 'Unable to parse "' + e.currentTarget.value + '" to a valid value. Input must match JSON format';
      utils.alert(message);
      logger.warn(message);
      utils.selectElements('js-model-property-value')[0].focus();
    }
  });
  utils.addEvent('js-model-property-value', 'keyup', function(e) {
    var which = (e.which || e.keyCode);
    if (which === 13) {
      e.currentTarget.blur();
    }
  });
  utils.addEvent('js-track-function', 'click', function(e) {
    var fnName = e.currentTarget.getAttribute('data-fn');
    var selectedFunction = _.findWhere(appData.selectedModel.objectFunctions, {
      name: fnName
    });
    selectedFunction.tracked = !selectedFunction.tracked;
    appData.selectedModel.toggleFunctionTracking(fnName, selectedFunction.tracked);
    utils.render();
  });
  utils.addEvent('js-show-inherited', 'change', function(e) {
    e.stopPropagation();
    appData.settings.showInheritedMethods = e.currentTarget.checked;
    utils.render();
  });
  utils.addEvent('js-add-new-event', 'blur', function(e) {
    var eventName = e.currentTarget.value;
    if (/^\s*$/.test(eventName)) {
      return;
    }
    var existing = _.findWhere(appData.selectedModel.customEvents, {
      name: eventName
    });
    if (!existing) {
      var listener = utils.addListener(appData.selectedModel.obj, eventName);
      appData.selectedModel.customEvents.push({
        name: eventName,
        listener: listener
      });
    }
    utils.render();
  });
  utils.addEvent('js-add-new-event', 'keyup', function(e) {
    var which = (e.which || e.keyCode);
    if (which === 13) {
      e.currentTarget.blur();
    }
  });
  utils.addEvent('js-untrack-event', 'click', function(e) {
    var eventName = utils.closest(e.currentTarget, 'js-tracked-event').getAttribute('data-key');
    var events = appData.selectedModel.customEvents;
    for (var i = 0; i < events.length; i++) {
      if (events[i].name === eventName) {
        utils.removeListener(appData.selectedModel.obj, events[i].name, events[i].listener);
        events.splice(i, 1);
        break;
      }
    }
    utils.render();
  });
  utils.addEvent('js-get-model-data', 'click', function() {
    appData.selectedModel.outputData = JSON.stringify(appData.selectedModel.obj);
    utils.render();
  });
  utils.addEvent('js-set-model-data', 'click', function() {
    var textbox = utils.selectElements('js-model-data')[0];
    appData.selectedModel.outputData = '';
    appData.selectedModel.obj.reset(JSON.parse(textbox.value));
    appData.updateSelectedModel();
  });
  utils.addEvent('js-reset-data', 'click', function() {
    appData.selectedModel.obj.reset(appData.selectedModel.obj.initialData);
    appData.updateSelectedModel();
  });
  utils.addEvent('js-remove-attribute', 'click', function(e) {
    e.stopPropagation();
    appData.selectedModel.obj.unset(e.currentTarget.getAttribute('data-key'));
    appData.updateSelectedModel();
  });
  utils.addEvent('js-add-attribute', 'click', function() {
    appData.settings.modelProperties = appData.settings.modelProperties || {};
    appData.settings.modelProperties.adding = true;
    utils.render();
  });
  utils.addEvent('js-cancel-adding-attribute', 'click', function() {
    appData.settings.modelProperties = appData.settings.modelProperties || {};
    appData.settings.modelProperties.adding = false;
    utils.render();
  });
  utils.addEvent('js-adding-attribute', 'submit', function(e) {
    e.preventDefault();
    var form = e.currentTarget;
    var name = form.name.value;
    var value;
    try {
      value = JSON.parse(form.value.value);
    } catch (ex) {
      value = form.value.value;
    }
    var model = appData.selectedModel.obj;
    if (model.has(name)) {
      alert('Model already has property named "' + name + '"');
    } else {
      model.set(name, value);
      appData.settings.modelProperties = appData.settings.modelProperties || {};
      appData.settings.modelProperties.adding = false;
      appData.updateSelectedModel();
    }
  });
};
<|endoftext|>


<commit_before>module.exports = {
    enabled: true,
    metadata:{
        name: 'application-core',
        version: '0.0.0',
        environment: 'development'
    },
    options: {
        prompt: '\u001b[33m${app.name} > \u001b[39m'
    }
};
<commit_msg>repl: use custom port<commit_after>module.exports = {
    enabled: true,
    metadata:{
        name: 'application-core',
        version: '0.0.0',
        environment: 'development'
    },
    options: {
        prompt: '\u001b[33m${app.name} > \u001b[39m'
    },
    port: 9090
};
<|endoftext|>


<commit_before>var page=$("#page_name").attr('data-page');

twttr.anywhere(function (T) {
	if(T.isConnected()){
		show_dropdown(T);
		$("#upload_file_btn").live("click", function(){
		var user_name=T.currentUser.data('screen_name');
		var d=new Date();
		d=d.toISOString();
		var tags=$("#upload_message").val().split(" ");
		var act_tags="", k=0;
		for(var j=0;j<tags.length;j++){
			if(tags[j].indexOf('#') == 0){
				act_tags=act_tags+" "+tags[j];
				act_tags=act_tags.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
				k++;
			}
		}
		act_tags=act_tags.substring(1,act_tags.length);
		var uid=$.couch.newUUID();
		uid="mytweet_"+uid;
		var doc={
			"_id": uid,
			"uploaded_by": user_name,
			"gravatar_url": "http://api.twitter.com/1/users/profile_image/"+user_name,
			"uploader_msg": $("#upload_message").val(),
			"created_at": d,
			"tags": act_tags.split(" ")
		};
		$.couch.db($db).saveDoc(doc,{
			success: function(data){
				var id=data.id;
				var stat=data.ok;
				if(stat){
					$("#uploadModal").modal('hide');
				}
			},
			error: function(data){
				console.log(data);
			}
		});
		return false;
	});
	}
	else{
		$("#uploadModal").on("shown",function(){
			$("#upload_file_btn").live("click", function(){
				if(T.isConnected()){

				}else{
					$("#uploadModal").modal('hide');
				$("#messages").html("
×You need to be logged in!
").hide().fadeIn(500);
				}
			});
		});
		$("#peepin").html('Login »').show();
	}
  $("#login").live("click",function(){
  	if(T.isConnected()){
  		show_dropdown(T);
  	}
  	else{
  		T.signIn();
  	}
  });
  $("#logout").live("click",function(){
  	twttr.anywhere.signOut();
  	window.location="index.html";
  });

});

function show_dropdown(T){
		var user=T.currentUser;
		var p=user.data('profile_image_url');
		var a=p.split('_');
		p=a[0]+"_"+a[1]+"_"+"mini.jpeg";
		$("#peepin").html('
 '+user.data("screen_name")+'

Home

Discussions

Files

Log out!

').hide().fadeIn('fast');
		if(page==="index.html"){
			$("#main-menu").hide();
			$("#tweet_div").html('Tweet »').hide().fadeIn(500);
		}
}
<commit_msg>discuss btn visibility if user is logged in<commit_after>var page=$("#page_name").attr('data-page');

twttr.anywhere(function (T) {
	if(T.isConnected()){
		show_dropdown(T);
		$("#upload_file_btn").live("click", function(){
		var user_name=T.currentUser.data('screen_name');
		var d=new Date();
		d=d.toISOString();
		var tags=$("#upload_message").val().split(" ");
		var act_tags="", k=0;
		for(var j=0;j<tags.length;j++){
			if(tags[j].indexOf('#') == 0){
				act_tags=act_tags+" "+tags[j];
				act_tags=act_tags.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
				k++;
			}
		}
		act_tags=act_tags.substring(1,act_tags.length);
		var uid=$.couch.newUUID();
		uid="mytweet_"+uid;
		var doc={
			"_id": uid,
			"uploaded_by": user_name,
			"gravatar_url": "http://api.twitter.com/1/users/profile_image/"+user_name,
			"uploader_msg": $("#upload_message").val(),
			"created_at": d,
			"tags": act_tags.split(" ")
		};
		$.couch.db($db).saveDoc(doc,{
			success: function(data){
				var id=data.id;
				var stat=data.ok;
				if(stat){
					$("#uploadModal").modal('hide');
				}
			},
			error: function(data){
				console.log(data);
			}
		});
		return false;
	});
	}
	else{
		$("#uploadModal").on("shown",function(){
			$("#upload_file_btn").live("click", function(){
				if(T.isConnected()){

				}else{
					$("#uploadModal").modal('hide');
				$("#messages").html("
×You need to be logged in!
").hide().fadeIn(500);
				}
			});
		});
		$("#peepin").html('Login »').show();
	}
  $("#login").live("click",function(){
  	if(T.isConnected()){
  		show_dropdown(T);
  	}
  	else{
  		T.signIn();
  	}
  });
  $("#logout").live("click",function(){
  	twttr.anywhere.signOut();
  	window.location="index.html";
  });

});

function show_dropdown(T){
		var user=T.currentUser;
		var p=user.data('profile_image_url');
		var a=p.split('_');
		p=a[0]+"_"+a[1]+"_"+"mini.jpeg";
		$("#peepin").html('
 '+user.data("screen_name")+'

Home

Discussions

Files

Log out!

').hide().fadeIn('fast');
		if(page==="index.html"){
			$("#main-menu").hide();
			$("#tweet_div").html('Tweet »').hide().fadeIn(500);
		}
		if(page==="discussion.html"){
			$("#main-menu").hide();
			$("#discuss_btn_div").html('Discuss »').hide().fadeIn(500);
		}
}
<|endoftext|>


<commit_before>import path from 'path';

import webpackCommonConfig from './webpack.common';

const testingSources = [
    path.resolve('src/components/')
];

export default {
    ...webpackCommonConfig,
    resolve: {
        ...webpackCommonConfig.resolve,
        alias: {
            ...webpackCommonConfig.resolve.alias,
            test: path.resolve('test')
        }
    },
    module: {
        preLoaders: [
            {
                test: /\.js$/,
                loader: 'rebem-layers',
                query: {
                    layers: [
                        require('rebem-core-components'),
                        require('rebem-theme-reset'),
                        {
                            path: path.resolve('src/components/'),
                            files: {
                                main: 'index.js',
                                styles: 'styles.less'
                            },
                            importFactory: true
                        }
                    ],
                    consumers: [
                        path.resolve('src/index.js'),
                        path.resolve('test/')
                    ]
                }
            },
            {
                test: /\.js$/,
                include: testingSources,
                loader: 'babel-istanbul',
                query: {
                    cacheDirectory: true
                }
            },
            {
                test: /\.js$/,
                exclude: [
                    ...testingSources,
                    path.resolve('node_modules/')
                ],
                loader: 'babel',
                query: {
                    cacheDirectory: true
                }
            }
        ],
        loaders: [
            ...webpackCommonConfig.module.loaders,
            {
                test: /\.css$/,
                loaders: [
                    'style',
                    'css?-minimize',
                    'postcss'
                ]
            },
            {
                test: /\.less$/,
                loaders: [
                    'style',
                    'css?-minimize',
                    'postcss',
                    'less'
                ]
            }
        ]
    }
};
<commit_msg>:space_invader: fix missing bootstrap layer in webpack.test config<commit_after>import path from 'path';

import webpackCommonConfig from './webpack.common';

const testingSources = [
    path.resolve('src/components/')
];

export default {
    ...webpackCommonConfig,
    resolve: {
        ...webpackCommonConfig.resolve,
        alias: {
            ...webpackCommonConfig.resolve.alias,
            test: path.resolve('test')
        }
    },
    module: {
        preLoaders: [
            {
                test: /\.js$/,
                loader: 'rebem-layers',
                query: {
                    layers: [
                        require('rebem-core-components'),
                        require('rebem-theme-reset'),
                        require('../src/theme-bootstrap'),
                        {
                            path: path.resolve('src/components/'),
                            files: {
                                main: 'index.js',
                                styles: 'styles.less'
                            },
                            importFactory: true
                        }
                    ],
                    consumers: [
                        path.resolve('src/index.js'),
                        path.resolve('test/')
                    ]
                }
            },
            {
                test: /\.js$/,
                include: testingSources,
                loader: 'babel-istanbul',
                query: {
                    cacheDirectory: true
                }
            },
            {
                test: /\.js$/,
                exclude: [
                    ...testingSources,
                    path.resolve('node_modules/')
                ],
                loader: 'babel',
                query: {
                    cacheDirectory: true
                }
            }
        ],
        loaders: [
            ...webpackCommonConfig.module.loaders,
            {
                test: /\.css$/,
                loaders: [
                    'style',
                    'css?-minimize',
                    'postcss'
                ]
            },
            {
                test: /\.less$/,
                loaders: [
                    'style',
                    'css?-minimize',
                    'postcss',
                    'less'
                ]
            }
        ]
    }
};
<|endoftext|>


<commit_before>import Backbone from "backbone"
import sinon from "sinon"
import articlesJSON from "./fixtures.coffee"
import fixtures from "desktop/test/helpers/fixtures.coffee"
import { extend, cloneDeep } from "lodash"

const rewire = require("rewire")("../routes")
const { articles, section, teamChannel } = rewire

describe("Articles routes", () => {
  let req
  let res
  let next
  let positronql

  beforeEach(() => {
    sinon.stub(Backbone, "sync")
    req = {
      params: {},
      query: {},
    }
    res = {
      render: sinon.stub(),
      locals: { sd: {} },
      redirect: sinon.stub(),
      backboneError: sinon.stub(),
    }
    next = sinon.stub()

    rewire.__set__(
      "topParselyArticles",
      sinon
        .stub()
        .yields([
          fixtures.parselyArticle,
          fixtures.parselyArticle,
          fixtures.parselyArticle,
        ])
    )

    positronql = sinon.stub().returns(
      Promise.resolve({
        articles: articlesJSON,
      })
    )
    rewire.__set__("positronql", positronql)
  })

  afterEach(() => {
    Backbone.sync.restore()
  })

  describe("#articles", () => {
    it("fetches published articles", () => {
      articles(req, res, next).then(() => {
        res.render.args[0][0].should.equal("articles")
        res.render.args[0][1].articles.length.should.equal(5)
      })
    })

    it("requests less than 50 articles", () => {
      articles(req, res, next).then(() => {
        positronql.args[0][0].query.should.containEql("limit: 50")
      })
    })
  })

  describe("#section", () => {
    it("renders the section with articles", () => {
      const sectionObject = extend(cloneDeep(fixtures.section), {
        slug: "foo",
      })
      section(req, res, next)
      Backbone.sync.args[0][2].success(sectionObject)
      Backbone.sync.args[1][2].data.section_id.should.equal(sectionObject.id)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("section")
      res.render.args[0][1].section
        .get("title")
        .should.equal(sectionObject.title)
    })

    it("nexts for an error because it uses a root url", () => {
      section(req, res, next)
      Backbone.sync.args[0][2].error()
      next.called.should.be.ok()
    })
  })

  describe("#teamChannel", () => {
    it("renders the channel with its articles", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "team",
      })
      req.path = "foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      Backbone.sync.args[1][2].data.ids.length.should.equal(4)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("team_channel")
      res.render.args[0][1].channel.get("name").should.equal(channel.name)
    })

    it("nexts if channel is not a team channel", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "editorial",
      })
      req.path = "/foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      next.called.should.be.ok()
    })

    it("errors if there is an issue fetching a team channel", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "editorial",
      })
      req.path = "/foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].error(channel)
      res.backboneError.called.should.be.ok()
    })

    it("handles query params", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "team",
      })
      req.path = "/foo?utm=campaign"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("team_channel")
      res.render.args[0][1].channel.get("name").should.equal(channel.name)
    })
  })
})
<commit_msg>add a test for showCollectionsRail<commit_after>import Backbone from "backbone"
import sinon from "sinon"
import articlesJSON from "./fixtures.coffee"
import fixtures from "desktop/test/helpers/fixtures.coffee"
import { extend, cloneDeep } from "lodash"

const rewire = require("rewire")("../routes")
const { articles, news, section, teamChannel } = rewire

describe("Articles routes", () => {
  let req
  let res
  let next
  let positronql

  beforeEach(() => {
    sinon.stub(Backbone, "sync")
    req = {
      params: {},
      query: {},
      user: {
        isAdmin: sinon.stub().returns(true),
      },
    }
    res = {
      render: sinon.stub(),
      locals: {
        sd: {
          EDITORIAL_COLLECTIONS_RAIL_QA: 1,
        },
      },
      redirect: sinon.stub(),
      backboneError: sinon.stub(),
    }
    next = sinon.stub()

    rewire.__set__(
      "topParselyArticles",
      sinon
        .stub()
        .yields([
          fixtures.parselyArticle,
          fixtures.parselyArticle,
          fixtures.parselyArticle,
        ])
    )

    positronql = sinon.stub().returns(
      Promise.resolve({
        articles: articlesJSON,
      })
    )
    rewire.__set__("positronql", positronql)
  })

  afterEach(() => {
    Backbone.sync.restore()
  })

  describe("#articles", () => {
    it("fetches published articles", () => {
      articles(req, res, next).then(() => {
        res.render.args[0][0].should.equal("articles")
        res.render.args[0][1].articles.length.should.equal(5)
      })
    })

    it("requests less than 50 articles", () => {
      articles(req, res, next).then(() => {
        positronql.args[0][0].query.should.containEql("limit: 50")
      })
    })
  })

  describe("#new", () => {
    it("correctly sets showCollectionsRail", () => {
      rewire.__set__(
        "positronql",
        sinon.stub().returns(Promise.resolve({ articles }))
      )
      const stitch = sinon.stub()
      rewire.__set__("stitch", stitch)
      news(req, res, next).then(() => {
        stitch.args[0][0].data.showCollectionsRail.should.equal(true)
      })
    })
  })

  describe("#section", () => {
    it("renders the section with articles", () => {
      const sectionObject = extend(cloneDeep(fixtures.section), {
        slug: "foo",
      })
      section(req, res, next)
      Backbone.sync.args[0][2].success(sectionObject)
      Backbone.sync.args[1][2].data.section_id.should.equal(sectionObject.id)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("section")
      res.render.args[0][1].section
        .get("title")
        .should.equal(sectionObject.title)
    })

    it("nexts for an error because it uses a root url", () => {
      section(req, res, next)
      Backbone.sync.args[0][2].error()
      next.called.should.be.ok()
    })
  })

  describe("#teamChannel", () => {
    it("renders the channel with its articles", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "team",
      })
      req.path = "foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      Backbone.sync.args[1][2].data.ids.length.should.equal(4)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("team_channel")
      res.render.args[0][1].channel.get("name").should.equal(channel.name)
    })

    it("nexts if channel is not a team channel", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "editorial",
      })
      req.path = "/foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      next.called.should.be.ok()
    })

    it("errors if there is an issue fetching a team channel", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "editorial",
      })
      req.path = "/foo"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].error(channel)
      res.backboneError.called.should.be.ok()
    })

    it("handles query params", () => {
      const channel = extend(cloneDeep(fixtures.channel), {
        slug: "foo",
        type: "team",
      })
      req.path = "/foo?utm=campaign"
      teamChannel(req, res, next)
      Backbone.sync.args[0][2].success(channel)
      Backbone.sync.args[1][2].success(fixtures.article)
      res.render.args[0][0].should.equal("team_channel")
      res.render.args[0][1].channel.get("name").should.equal(channel.name)
    })
  })
})
<|endoftext|>


<commit_before>import React from 'react';

import {shallow, mount, render} from 'enzyme';
import {expect} from 'chai';
import sinon from 'sinon';

import Marker from '../../components/Marker';

// let google = {};
// google.maps = {};
// google.maps.LatLng = function(lat, lng, opt_noWrap) {};

describe('Marker', () => {
  let map = null, google = global.google;
  let sandbox;
  let LatLng = null;
  let location;

  beforeEach(() => {
    sandbox = sinon.sandbox.create();

    map = {}
    location = {lat: 37.759703, lng: -122.428093}

    sandbox.stub(google.maps, 'Map').returns(google.maps.Map);
    // sandbox.stub(google.maps, 'Marker').returns(google.maps.Marker);
  })

  afterEach(() => {
    sandbox.restore();
  })

  it('accepts a `map` and a `google` prop', () => {
    const wrapper = mount(<Marker google={google} map={map} />);
    expect(wrapper.props().google).to.equal(google);
    expect(wrapper.props().map).to.equal(map);
  });

  describe('LatLng', () => {
    let wrapper;
    beforeEach(() => {
      sandbox.stub(google.maps, 'LatLng')
        .returns(sinon.createStubInstance(google.maps.LatLng));
      sandbox.spy(google.maps, 'Marker')
      wrapper = mount(<Marker google={google}
                              position={location} />);
    });

    it('creates a location from the position prop', () => {
      wrapper.setProps({map: map})
      sinon.assert
        .calledWith(google.maps.LatLng, location.lat, location.lng)
    });

    it('creates a Marker from the position prop', () => {
      wrapper.setProps({map: map})
      sinon.assert.called(google.maps.Marker)
    });

  })

})
<commit_msg>fix broken test<commit_after>import React from 'react';

import {shallow, mount, render} from 'enzyme';
import {expect} from 'chai';
import sinon from 'sinon';

import Marker from '../../components/Marker';

// let google = {};
// google.maps = {};
// google.maps.LatLng = function(lat, lng, opt_noWrap) {};

describe('Marker', () => {
  let map = null, google = global.google;
  let sandbox;
  let LatLng = null;
  let location;

  beforeEach(() => {
    sandbox = sinon.sandbox.create();

    map = {}
    location = {lat: 37.759703, lng: -122.428093}

    sandbox.stub(google.maps, 'Map').returns(google.maps.Map);
    // sandbox.stub(google.maps, 'Marker').returns(google.maps.Marker);
  })

  afterEach(() => {
    sandbox.restore();
  })

  it('accepts a `map` and a `google` prop', () => {
    const wrapper = mount(<Marker google={google}
                                  map={map}
                                  position={location} />);
    expect(wrapper.props().google).to.equal(google);
    expect(wrapper.props().map).to.equal(map);
  });

  describe('LatLng', () => {
    let wrapper;
    beforeEach(() => {
      sandbox.stub(google.maps, 'LatLng')
        .returns(sinon.createStubInstance(google.maps.LatLng));
      sandbox.spy(google.maps, 'Marker')
      wrapper = mount(<Marker google={google}
                              position={location} />);
    });

    it('creates a location from the position prop', () => {
      wrapper.setProps({map: map})
      sinon.assert
        .calledWith(google.maps.LatLng, location.lat, location.lng)
    });

    it('creates a Marker from the position prop', () => {
      wrapper.setProps({map: map})
      sinon.assert.called(google.maps.Marker)
    });

  })

})
<|endoftext|>


<commit_before>#!/usr/bin/env seed
history = [];
with (Seed)
{
	while(1)
	{
		try
		{
			item = readline("> ");
			history.push(item);
			print(eval(item));
		}
		catch(e)
		{
			print(e.name + " " + e.message);
		}
	}
}
<commit_msg>Fix trash in REPL.<commit_after>#!/usr/bin/env seed
with (Seed)
{
	while(1)
	{
		try
		{
			item = readline("> ");
			print(eval(item));
		}
		catch(e)
		{
			print(e.name + " " + e.message);
		}
	}
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';

import DraftailEditor, { ENTITY_TYPE } from '../lib';

// =============================================================================
// A `Source` provides a wrapper around whatever chooser you're using.
// All it needs to know about is when the value is updated so it can close.
// =============================================================================

// import WagtailImageSource from './sources/WagtailImageSource';
// import WagtailDocumentSource from './sources/WagtailDocumentSource';
// import GenericModelSource from './sources/GenericModelSource';
import BasicLinkSource from './sources/BasicLinkSource';
import BasicImageSource from './sources/BasicImageSource';
import BasicEmbedSource from './sources/BasicEmbedSource';

import Link, { findLinkEntities } from './entities/Link';
// import Document, { findDocumentEntities } from './entities/Document';
// import Model, { findModelEntities } from './entities/Model';

const mount = document.querySelector('[data-mount-test]');

const options = {
    modelPickerOptions: [],
    MODEL: ENTITY_TYPE.MODEL,
    imageFormats: [],
    // Modals and other external sources of data
    mediaControls: [
        {
            entity: ENTITY_TYPE.IMAGE,
            label: 'Image',
            icon: 'image',
        },
        {
            entity: ENTITY_TYPE.EMBED,
            label: 'Embed',
            icon: 'media',
        },
    ],
    dialogControls: [
        {
            entity: ENTITY_TYPE.LINK,
            label: 'Link',
            icon: 'link',
        },
        {
            entity: ENTITY_TYPE.DOCUMENT,
            label: 'Document',
            icon: 'doc-full',
        },
    ],
    sources: [
        { entity: ENTITY_TYPE.LINK, control: BasicLinkSource },
        // { entity: ENTITY_TYPE.DOCUMENT, control: WagtailDocumentSource },
        // { entity: ENTITY_TYPE.MODEL, control: GenericModelSource },
        { entity: ENTITY_TYPE.IMAGE, control: BasicImageSource },
        { entity: ENTITY_TYPE.EMBED, control: BasicEmbedSource },
    ],
    // In-line decorators that format text in interesting ways.
    decorators: [
        { strategy: findLinkEntities, component: Link },
        // { strategy: findModelEntities, component: Model },
        // { strategy: findDocumentEntities, component: Document },
    ],
    BLOCK_TYPES: [
        { label: 'H2', style: 'header-two' },
        { label: 'H3', style: 'header-three' },
        { label: 'H4', style: 'header-four' },
        { label: 'H5', style: 'header-five' },
        { label: 'Intro', style: 'intro-text', icon: 'bin', element: 'pre', className: 'u-blue' },
        { label: 'Blockquote', style: 'blockquote', icon: 'openquote' },
        { label: 'UL', style: 'unordered-list-item', icon: 'list-ul' },
        { label: 'OL', style: 'ordered-list-item', icon: 'list-ol' },
    ],

    INLINE_STYLES: [
        { label: 'Bold', style: 'BOLD', icon: 'bold' },
        { label: 'Italic', style: 'ITALIC', icon: 'italic' },
        // {label: 'Underline', style: 'UNDERLINE'},
        // {label: 'Monospace', style: 'CODE'},
        // {label: 'Strikethrough', style: 'STRIKETHROUGH'},
    ],
};

const onSave = (rawContentState) => {
    const serialised = JSON.stringify(rawContentState);
    sessionStorage.setItem('entities:rawContentState', serialised);
};

const editor = (
    <DraftailEditor
        rawContentState={JSON.parse(sessionStorage.getItem('entities:rawContentState')) || {}}
        options={options}
        onSave={onSave}
    />
);

ReactDOM.render(editor, mount);
<commit_msg>Enable HR and BR on test page<commit_after>import React from 'react';
import ReactDOM from 'react-dom';

import DraftailEditor, { ENTITY_TYPE } from '../lib';

// =============================================================================
// A `Source` provides a wrapper around whatever chooser you're using.
// All it needs to know about is when the value is updated so it can close.
// =============================================================================

// import WagtailImageSource from './sources/WagtailImageSource';
// import WagtailDocumentSource from './sources/WagtailDocumentSource';
// import GenericModelSource from './sources/GenericModelSource';
import BasicLinkSource from './sources/BasicLinkSource';
import BasicImageSource from './sources/BasicImageSource';
import BasicEmbedSource from './sources/BasicEmbedSource';

import Link, { findLinkEntities } from './entities/Link';
// import Document, { findDocumentEntities } from './entities/Document';
// import Model, { findModelEntities } from './entities/Model';

const mount = document.querySelector('[data-mount-test]');

const options = {
    enableHorizontalRule: true,
    enableLineBreak: true,
    modelPickerOptions: [],
    MODEL: ENTITY_TYPE.MODEL,
    imageFormats: [],
    // Modals and other external sources of data
    mediaControls: [
        {
            entity: ENTITY_TYPE.IMAGE,
            label: 'Image',
            icon: 'image',
        },
        {
            entity: ENTITY_TYPE.EMBED,
            label: 'Embed',
            icon: 'media',
        },
    ],
    dialogControls: [
        {
            entity: ENTITY_TYPE.LINK,
            label: 'Link',
            icon: 'link',
        },
        {
            entity: ENTITY_TYPE.DOCUMENT,
            label: 'Document',
            icon: 'doc-full',
        },
    ],
    sources: [
        { entity: ENTITY_TYPE.LINK, control: BasicLinkSource },
        // { entity: ENTITY_TYPE.DOCUMENT, control: WagtailDocumentSource },
        // { entity: ENTITY_TYPE.MODEL, control: GenericModelSource },
        { entity: ENTITY_TYPE.IMAGE, control: BasicImageSource },
        { entity: ENTITY_TYPE.EMBED, control: BasicEmbedSource },
    ],
    // In-line decorators that format text in interesting ways.
    decorators: [
        { strategy: findLinkEntities, component: Link },
        // { strategy: findModelEntities, component: Model },
        // { strategy: findDocumentEntities, component: Document },
    ],
    BLOCK_TYPES: [
        { label: 'H2', style: 'header-two' },
        { label: 'H3', style: 'header-three' },
        { label: 'H4', style: 'header-four' },
        { label: 'H5', style: 'header-five' },
        { label: 'Intro', style: 'intro-text', icon: 'bin', element: 'pre', className: 'u-blue' },
        { label: 'Blockquote', style: 'blockquote', icon: 'openquote' },
        { label: 'UL', style: 'unordered-list-item', icon: 'list-ul' },
        { label: 'OL', style: 'ordered-list-item', icon: 'list-ol' },
    ],

    INLINE_STYLES: [
        { label: 'Bold', style: 'BOLD', icon: 'bold' },
        { label: 'Italic', style: 'ITALIC', icon: 'italic' },
        // {label: 'Underline', style: 'UNDERLINE'},
        // {label: 'Monospace', style: 'CODE'},
        // {label: 'Strikethrough', style: 'STRIKETHROUGH'},
    ],
};

const onSave = (rawContentState) => {
    const serialised = JSON.stringify(rawContentState);
    sessionStorage.setItem('entities:rawContentState', serialised);
};

const editor = (
    <DraftailEditor
        rawContentState={JSON.parse(sessionStorage.getItem('entities:rawContentState')) || {}}
        options={options}
        onSave={onSave}
    />
);

ReactDOM.render(editor, mount);
<|endoftext|>