<commit_before>var dotest = require ('dotest');
var app = require ('./');

// Setup
// $ EUROPEANA_KEY=abc123 npm test
var apikey = process.env.EUROPEANA_APIKEY || null;
var timeout = process.env.EUROPEANA_TIMEOUT || 5000;

var europeana = app (apikey, timeout);

dotest.add ('Module', function (test) {
  test ()
    .isFunction ('fail', 'exports', app)
    .isFunction ('fail', 'module', europeana)
    .done ();
});

dotest.add ('search', function (test) {
  var props = {
    query: 'who:"laurent de la hyre"'
  };

  europeana ('search', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .done ();
  });
});

dotest.add ('record', function (test) {
  var record = '9200365/BibliographicResource_1000055039444';
  var props = {
    profile: 'params'
  };

  europeana ('record/' + record, props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .done ();
  });
});

dotest.add ('translateQuery', function (test) {
  var props = {
    languageCodes: 'nl,en,hu',
    term: 'painting'
  };

  europeana ('translateQuery', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.translations', data && data.translations)
      .done ();
  });
});

dotest.add ('providers normal', function (test) {
  europeana ('providers', function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.items', data && data.items)
      .done ();
  });
});

dotest.add ('providers params', function (test) {
  var params = {
    pagesize: 3
  };

  europeana ('providers', params, function (err, data) {
    var items = data && data.items;

    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.items', items)
      .isExactly ('warn', 'data.items.length', items && items.length, 3)
      .done ();
  });
});

/*
// Suggestions in unavailable
// http://labs.europeana.eu/api/suggestions
dotest.add ('suggestions', function (test) {
  var props = {
    query: 'laurent de la hyre',
    rows: 10
  };

  app ('suggestions', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .done ();
  });
});
*/

// Start the tests
dotest.run ();
<commit_msg>Test(tests): Add Error: apikey missing<commit_after>var dotest = require ('dotest');
var app = require ('./');

// Setup
// $ EUROPEANA_KEY=abc123 npm test
var apikey = process.env.EUROPEANA_APIKEY || null;
var timeout = process.env.EUROPEANA_TIMEOUT || 5000;

var europeana = app (apikey, timeout);

dotest.add ('Module', function (test) {
  test ()
    .isFunction ('fail', 'exports', app)
    .isFunction ('fail', 'module', europeana)
    .done ();
});

dotest.add ('search', function (test) {
  var props = {
    query: 'who:"laurent de la hyre"'
  };

  europeana ('search', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .done ();
  });
});

dotest.add ('record', function (test) {
  var record = '9200365/BibliographicResource_1000055039444';
  var props = {
    profile: 'params'
  };

  europeana ('record/' + record, props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .done ();
  });
});

dotest.add ('translateQuery', function (test) {
  var props = {
    languageCodes: 'nl,en,hu',
    term: 'painting'
  };

  europeana ('translateQuery', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.translations', data && data.translations)
      .done ();
  });
});

dotest.add ('providers normal', function (test) {
  europeana ('providers', function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.items', data && data.items)
      .done ();
  });
});

dotest.add ('providers params', function (test) {
  var params = {
    pagesize: 3
  };

  europeana ('providers', params, function (err, data) {
    var items = data && data.items;

    test (err)
      .isObject ('fail', 'data', data)
      .isNotEmpty ('warn', 'data', data)
      .isArray ('warn', 'data.items', items)
      .isExactly ('warn', 'data.items.length', items && items.length, 3)
      .done ();
  });
});

dotest.add ('Error: apikey missing', function (test) {
  var tmp = app ();

  tmp ('providers', function (err, data) {
    test ()
      .isError ('fail', 'err', err)
      .isExactly ('fail', 'err.message', err && err.message, 'apikey missing')
      .isUndefined ('fail', 'data', data)
      .done ();
  });
});

/*
// Suggestions in unavailable
// http://labs.europeana.eu/api/suggestions
dotest.add ('suggestions', function (test) {
  var props = {
    query: 'laurent de la hyre',
    rows: 10
  };

  app ('suggestions', props, function (err, data) {
    test (err)
      .isObject ('fail', 'data', data)
      .done ();
  });
});
*/

// Start the tests
dotest.run ();
<|endoftext|>


<commit_before>beforeEach(() => {
  jest.resetModules()
  jest.clearAllMocks()
})

afterAll(() => require('../../lib/statsd').close())

test('worker throws away unimplemented job', async () => {
  expect.assertions(2)

  const worker = require('../../lib/worker')

  await worker(
    expect.anything(),
    {
      ack: expect.anything(),
      nack: (job, allUpTo, requeue) => {
        expect(allUpTo).toBeFalsy()
        expect(requeue).toBeFalsy()
      }
    },
    {
      content: Buffer.from(JSON.stringify({ name: 'unimplemented-job' }))
    }
  )
})

test('worker throws away unimplemented job action', async () => {
  expect.assertions(3)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => {
      throw new Error('not implemented')
    }
    return path
  })
  const path = require('path')
  const worker = require('../../lib/worker')

  expect(() => {
    path.jobPath('unimplemented-job')
  }).toThrow('not implemented')

  await worker(
    expect.anything(),
    {
      ack: expect.anything(),
      nack: (job, allUpTo, requeue) => {
        expect(allUpTo).toBeFalsy()
        expect(requeue).toBeFalsy()
      }
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'unimplemented-job', accountId: 123
      }))
    }
  )
})

test('worker requeues job on error, then throws away', async () => {
  expect.assertions(4)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => {
      throw new Error('something went wrong')
    }
    return path
  })
  const path = require('path')
  const worker = require('../../lib/worker')

  expect(() => {
    path.jobPath('failing-job')
  }).toThrow('something went wrong')

  await worker(
    expect.anything(),
    {
      ack: expect.anything(),
      nack: () => expect(true).toBeTruthy()
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'failing-job', accountId: 123
      })),
      fields: {}
    }
  )

  await worker(
    expect.anything(),
    {
      ack: expect.anything(),
      nack: (job, allUpTo, requeue) => {
        expect(allUpTo).toBeFalsy()
        expect(requeue).toBeFalsy()
      }
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'failing-job', accountId: 123
      })),
      fields: {
        redelivered: true
      }
    }
  )
})

test('worker acks job on success w/o further work', async () => {
  expect.assertions(2)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => {}
    return path
  })
  const path = require('path')
  const worker = require('../../lib/worker')

  expect(() => {
    path.jobPath('successful-job')
  }).not.toThrow()

  await worker(
    expect.anything(),
    {
      ack: expect(true).toBeTruthy(),
      nack: () => expect.anything()
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'successful-job',
        repository: {
          owner: {
            id: 111
          },
          full_name: 'testOrg/testRepo'
        }
      }))
    }
  )
})

test('worker schedules further jobs on success', async () => {
  expect.assertions(3)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => [
      {
        data: true,
        plan: 'free'
      },
      {
        data: true,
        plan: 'supporter'
      },
      {
        data: true
      },
      {
        data: false
      }
    ]
    return path
  })
  const path = require('path')
  const worker = require('../../lib/worker')

  expect(() => {
    path.jobPath('successful-job')
  }).not.toThrow()

  await worker(
    expect(true).toBeTruthy(),
    {
      ack: expect(true).toBeTruthy(),
      nack: () => expect.anything()
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'successful-job', accountId: 234
      }))
    }
  )
})

test('worker schedules further monorepo-supervisor jobs on success', async () => {
  expect.assertions(7)

  const monorepoSupervisorJobData = { content: Buffer.from(JSON.stringify({name: 'monorepo-supervisor'})) }

  jest.mock('../../jobs/monorepo-supervisor', () => {
    return async () => [
      {
        data: {
          name: 'registry-change',
          dependency: 'jest'
        }
      },
      {
        data: {
          name: 'registry-change',
          dependency: 'angular'
        }
      },
      {
        data: {
          name: 'registry-change',
          dependency: 'pouchdb'
        }
      }
    ]
  })

  const worker = require('../../lib/worker')

  await worker(
    (data) => {
      const job = JSON.parse(data.toString())
      expect(job.name).toBe('registry-change')
      expect(['jest', 'angular', 'pouchdb'].includes(job.dependency)).toBeTruthy()
    },
    {
      ack: (arg) => {
        const job = JSON.parse(arg.content.toString())
        expect(job.name).toBe('monorepo-supervisor')
      },
      nack: () => expect.anything()
    },
    monorepoSupervisorJobData
  )
})

test('worker requeues job on scheduling error, then throws away', async () => {
  expect.assertions(5)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => [
      {
        data: true
      },
      {
        data: true
      }
    ]
    return path
  })
  const path = require('path')
  const worker = require('../../lib/worker')

  expect(() => {
    path.jobPath('failing-schedule')
  }).not.toThrow()

  await worker(
    () => {
      throw new Error('scheduling fail')
    },
    {
      ack: expect.anything(),
      nack: () => expect(true).toBeTruthy()
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'failing-schedule', accountId: 233
      })),
      fields: {}
    }
  )

  await worker(
    () => {
      throw new Error('scheduling fail')
    },
    {
      ack: expect(true).toBeTruthy(),
      nack: (job, allUpTo, requeue) => {
        expect(allUpTo).toBeFalsy()
        expect(requeue).toBeFalsy()
      }
    },
    {
      content: Buffer.from(JSON.stringify({
        name: 'failing-schedule', accountId: 344
      })),
      fields: {
        redelivered: true
      }
    }
  )
})

test('worker measures runtime and sends it to statsd with tag', async () => {
  expect.assertions(4)

  jest.mock('path', () => {
    const path = require.requireActual('path')
    path.jobPath = (job) => [
      {
        data: true,
        plan: 'free'
      },
      {
        data: true,
        plan: 'supporter'
      },
      {
        data: true
      },
      {
        data: false
      }
    ]
    return path
  })
  const path = require('path')

  expect(() => {
    path.jobPath('update-payments')
  }).not.toThrow()

  jest.mock('../../lib/statsd', () => {
    return {
      increment: jest.fn(),
      gauge: jest.fn()
    }
  })
  const statsd = require('../../lib/statsd')

  const worker = require('../../lib/worker')
  await worker(
    expect.anything(),
    {
      ack: () => {},
      nack: () => {}
    }, {
      content: Buffer.from(JSON.stringify({ name: 'update-payments', accountId: '123' })),
      fields: ['hello']

    }
  )
  expect(statsd.gauge).toHaveBeenCalled()
  expect(statsd.gauge).toHaveBeenCalledTimes(1)
  expect(statsd.gauge).toHaveBeenCalledWith('job_runtime', expect.any(Number), {tag: 'update-payments'})
})
<commit_msg>test(worker): fix the tests<commit_after>const dbs = require('../../lib/dbs')
const removeIfExists = require('../helpers/remove-if-exists')

describe('worker', () => {
  const emptyScheduleJob = () => {}

  beforeAll(async () => {
    const { installations, repositories } = await dbs()
    await installations.put({
      _id: 'worker_111',
      installation: 'worker_111'
    })
    await repositories.put({
      _id: 'worker_111',
      fullName: 'lisa/monorepo'
    })
  })

  beforeEach(() => {
    jest.resetModules()
    jest.clearAllMocks()
  })

  afterAll(async () => {
    require('../../lib/statsd').close()
    const { installations, repositories } = await dbs()
    await Promise.all([
      removeIfExists(installations, 'worker_111'),
      removeIfExists(repositories, 'worker_111')
    ])
  })

  test('worker throws away unimplemented job', async () => {
    expect.assertions(3)

    const worker = require('../../lib/worker')

    await worker(
      emptyScheduleJob,
      {
        ack: () => {},
        nack: (job, allUpTo, requeue) => {
          const jobResult = JSON.parse(job.content.toString())
          expect(jobResult.name).toEqual('unimplemented-job')
          expect(job).toBeTruthy()
          expect(allUpTo).toBeFalsy()
          expect(requeue).toBeFalsy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({ name: 'unimplemented-job' }))
      }
    )
  })

  test('worker throws away unimplemented job action', async () => {
    expect.assertions(4)

    jest.mock('path', () => {
      const path = require.requireActual('path')
      path.jobPath = (job) => {
        throw new Error('not implemented')
      }
      return path
    })
    const path = require('path')
    const worker = require('../../lib/worker')

    expect(() => {
      path.jobPath('unimplemented-job')
    }).toThrow('not implemented')

    await worker(
      emptyScheduleJob,
      {
        ack: () => {},
        nack: (job, allUpTo, requeue) => {
          const jobResult = JSON.parse(job.content.toString())
          expect(jobResult.name).toEqual('unimplemented-job')
          expect(job).toBeTruthy()
          expect(allUpTo).toBeFalsy()
          expect(requeue).toBeFalsy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({
          name: 'unimplemented-job', accountId: 123
        }))
      }
    )
  })

  test('worker requeues job on error, then throws away', async () => {
    expect.assertions(5)

    jest.mock('path', () => {
      const path = require.requireActual('path')
      path.jobPath = (job) => {
        throw new Error('something went wrong')
      }
      return path
    })
    const path = require('path')
    const worker = require('../../lib/worker')

    expect(() => {
      path.jobPath('failing-job')
    }).toThrow('something went wrong')

    await worker(
      emptyScheduleJob,
      {
        ack: () => {},
        nack: (job) => {
          const jobResult = JSON.parse(job.content.toString())
          expect(jobResult.name).toEqual('failing-job')
          expect(job).toBeTruthy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({
          name: 'failing-job', accountId: 123
        })),
        fields: {}
      }
    )

    await worker(
      emptyScheduleJob,
      {
        ack: () => {},
        nack: (job, allUpTo, requeue) => {
          const jobResult = JSON.parse(job.content.toString())
          expect(jobResult.name).toEqual('failing-job')
          expect(job).toBeTruthy()
          expect(allUpTo).toBeFalsy()
          expect(requeue).toBeFalsy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({
          name: 'failing-job', accountId: 123
        })),
        fields: {
          redelivered: true
        }
      }
    )
  })

  test('worker acks job on success w/o further work', async () => {
    expect.assertions(2)

    const invalidConfigJob = {
      fields: {redelivered: false},
      content: Buffer.from(JSON.stringify({
        name: 'invalid-config-file',
        repositoryId: 'worker_111',
        accountId: 'worker_111',
        messages: ['The group name `#invalid#groupname#` is invalid. Group names may only contain alphanumeric characters and underscores (a-zA-Z_).']
      }))
    }
    jest.mock('../../jobs/invalid-config-file', () => () => true)
    const worker = require('../../lib/worker')

    await worker(
      emptyScheduleJob,
      {
        ack: (arg) => {
          const job = JSON.parse(arg.content.toString())
          expect(job.name).toEqual('invalid-config-file')
          expect(job.accountId).toEqual('worker_111')
        },
        nack: () => {}
      },
      invalidConfigJob
    )
  })

  test('worker schedules further jobs on success', async () => {
    expect.assertions(3)

    const installationJob = {
      fields: {redelivered: false},
      content: Buffer.from(JSON.stringify({
        name: 'create-version-branch',
        repositoryId: '222',
        accountId: 222
      }))
    }
    jest.mock('../../jobs/create-version-branch', () => {
      return async () => [
        {
          data: {
            name: 'create-branch',
            repositoryId: 'worker_111',
            accountId: 'worker_111'
          }
        },
        {
          data: {
            name: 'create-branch',
            repositoryId: 'worker_111',
            accountId: 'worker_111'
          }
        }

      ]
    })
    const worker = require('../../lib/worker')

    await worker(
      (data) => {
        const job = JSON.parse(data.toString())
        expect(job.name).toEqual('create-branch')
      },
      {
        ack: (arg) => {
          const job = JSON.parse(arg.content.toString())
          expect(job.name).toEqual('create-version-branch')
        },
        nack: () => {}
      },
      installationJob
    )
  })

  test('worker schedules further monorepo-supervisor jobs on success', async () => {
    expect.assertions(7)

    const monorepoSupervisorJobData = { content: Buffer.from(JSON.stringify({name: 'monorepo-supervisor'})) }

    jest.mock('../../jobs/monorepo-supervisor', () => {
      return async () => [
        {
          data: {
            name: 'registry-change',
            dependency: 'jest'
          }
        },
        {
          data: {
            name: 'registry-change',
            dependency: 'angular'
          }
        },
        {
          data: {
            name: 'registry-change',
            dependency: 'pouchdb'
          }
        }
      ]
    })

    const worker = require('../../lib/worker')

    await worker(
      (data) => {
        const job = JSON.parse(data.toString())
        expect(job.name).toEqual('registry-change')
        expect(['jest', 'angular', 'pouchdb'].includes(job.dependency)).toBeTruthy()
      },
      {
        ack: (arg) => {
          const job = JSON.parse(arg.content.toString())
          expect(job.name).toEqual('monorepo-supervisor')
        },
        nack: () => {}
      },
      monorepoSupervisorJobData
    )
  })

  test('worker requeues job on scheduling error, then throws away', async () => {
    expect.assertions(7)

    jest.mock('path', () => {
      const path = require.requireActual('path')
      path.jobPath = (job) => [
        {
          data: true
        },
        {
          data: true
        }
      ]
      return path
    })
    const path = require('path')
    const worker = require('../../lib/worker')

    expect(() => {
      path.jobPath('failing-schedule')
    }).not.toThrow()

    await worker(
      () => {
        throw new Error('scheduling fail')
      },
      {
        ack: () => {},
        nack: (job, allUpTo, requeue) => {
          const jobRes = JSON.parse(job.content.toString())
          expect(jobRes.name).toEqual('failing-schedule')
          expect(job).toBeTruthy()
          expect(allUpTo).toBeFalsy()
          expect(requeue).toBeFalsy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({
          name: 'failing-schedule', accountId: 233
        })),
        fields: {}
      }
    )

    await worker(
      () => {
        throw new Error('scheduling fail')
      },
      {
        ack: () => {},
        nack: (job, allUpTo, requeue) => {
          const jobRes = JSON.parse(job.content.toString())
          expect(jobRes.name).toEqual('failing-schedule')
          expect(job).toBeTruthy()
          expect(allUpTo).toBeFalsy()
          expect(requeue).toBeFalsy()
        }
      },
      {
        content: Buffer.from(JSON.stringify({
          name: 'failing-schedule', accountId: 344
        })),
        fields: {
          redelivered: true
        }
      }
    )
  })

  test('worker measures runtime and sends it to statsd with tag', async () => {
    expect.assertions(4)

    jest.mock('path', () => {
      const path = require.requireActual('path')
      path.jobPath = (job) => [
        {
          data: true,
          plan: 'free'
        },
        {
          data: true,
          plan: 'supporter'
        },
        {
          data: true
        },
        {
          data: false
        }
      ]
      return path
    })
    const path = require('path')

    expect(() => {
      path.jobPath('update-payments')
    }).not.toThrow()

    jest.mock('../../lib/statsd', () => {
      return {
        increment: jest.fn(),
        gauge: jest.fn()
      }
    })
    const statsd = require('../../lib/statsd')

    const worker = require('../../lib/worker')
    await worker(
      emptyScheduleJob,
      {
        ack: () => {},
        nack: () => {}
      }, {
        content: Buffer.from(JSON.stringify({ name: 'update-payments', accountId: '123' })),
        fields: ['hello']
      }
    )
    expect(statsd.gauge).toHaveBeenCalled()
    expect(statsd.gauge).toHaveBeenCalledTimes(1)
    expect(statsd.gauge).toHaveBeenCalledWith('job_runtime', expect.any(Number), {tag: 'update-payments'})
  })
})
<|endoftext|>


<commit_before>const test = require('tape');
const isPlainObj = require('is-plain-obj');
const tempWrite = require('temp-write');
const eslint = require('eslint');
const conf = require('./');
const reactConf = require('./browser');

function runEslint(str, configuration) {
  const linter = new eslint.CLIEngine({
    useEslintrc: false,
    configFile: tempWrite.sync(JSON.stringify(configuration)),
  });

  return linter.executeOnText(str).results[0].messages;
}

test('base rules', t => {
  t.plan(6);

  t.ok(isPlainObj(conf), 'should exist');
  t.ok(isPlainObj(conf.rules), 'should have rules configuration');

  const errors = runEslint(
    `var foo = function foo() {};
foo()
const arr = [
  1,
  2
];
`,
    conf
  );

  t.equal(errors[0].ruleId, 'no-var', 'should error when using var');
  t.equal(errors[2].ruleId, 'no-unused-vars', 'should error variables not used');
  t.equal(errors[3].ruleId, 'comma-dangle', 'should error when not using commas in multie-line arays');
});

test('react rules', t => {
  t.plan(3);

  t.ok(isPlainObj(reactConf), 'should exist');
  t.ok(isPlainObj(reactConf.rules), 'should have rules configuration');

  const errors = runEslint(
    `import React, { Component } from 'react';
import { observer } from 'mobx-react';

@observer
export default class Patient extends Component {
  render() {
    return (

Hello

    );
  }
}
`,
    reactConf
  );

  t.equal(errors[0].ruleId, 'import/no-extraneous-dependencies', 'should error modules not declare in package.json');
});
<commit_msg>test(browser): fix test for unused var<commit_after>const test = require('tape');
const isPlainObj = require('is-plain-obj');
const tempWrite = require('temp-write');
const eslint = require('eslint');
const conf = require('./');
const reactConf = require('./browser');

function runEslint(str, configuration) {
  const linter = new eslint.CLIEngine({
    useEslintrc: false,
    configFile: tempWrite.sync(JSON.stringify(configuration)),
  });

  return linter.executeOnText(str).results[0].messages;
}

test('base rules', t => {
  t.plan(4);

  t.ok(isPlainObj(conf), 'should exist');
  t.ok(isPlainObj(conf.rules), 'should have rules configuration');

  const errors = runEslint(
    `var foo = function foo() {};
foo()
const arr = [
  1,
  2
];
`,
    conf
  );

  t.equal(errors[0].ruleId, 'no-var', 'should error when using var');
  t.equal(errors[1].ruleId, 'no-unused-vars', 'should error variables not used');
});

test('react rules', t => {
  t.plan(3);

  t.ok(isPlainObj(reactConf), 'should exist');
  t.ok(isPlainObj(reactConf.rules), 'should have rules configuration');

  const errors = runEslint(
    `import React, { Component } from 'react';
import { observer } from 'mobx-react';

@observer
export default class Patient extends Component {
  render() {
    return (

Hello

    );
  }
}
`,
    reactConf
  );

  t.equal(errors[2].ruleId, 'no-unused-vars', 'should error variables not used');
});
<|endoftext|>


<commit_before>'use strict'

var colors = require('colors/safe')
var fs = require('fs')
var glob = require('glob')
var toc = require('markdown-toc')
var urlModule = require('url')
var markdownLinkCheck = require('markdown-link-check')
var path = require('path')

var files = glob.sync('**/*.md', { ignore: ['node_modules/**/*.md'] })

var tocCache = new Map()

function getToc(file) {
    file = path.normalize(file)
    if (tocCache.has(file)) {
        return tocCache.get(file)
    } else {
        var result = toc(fs.readFileSync(file).toString()).content
        tocCache.set(file, result)
        return result
    }
}

files.forEach(function (file) {
  var markdown = fs.readFileSync(file).toString()

  markdownLinkCheck(markdown, {
    baseUrl: path.basename(__dirname) + '/'
  }, function (err, results) {
    if (err) {
      console.error('Error', err)
      return
    }

    console.log('Reading: ' + file)

    // Get a list of all headers so we can verify intra-document links.
    var markdownToc = getToc(file)

    results.forEach(function (result) {
      var url = new URL(result.link, urlModule.pathToFileURL(file));
      if (url.protocol == 'file:' && !result.link.match(/ \(.*\)$/)) {
          var target = urlModule.fileURLToPath(url);
          if (!fs.existsSync(target)) {
              process.exitCode = 1
              console.log(colors.red(`Missing file: ${result.link}`))
              return;
          }

          if (url.hash === '') return;
          var toc = getToc(target)

          if (toc.includes(url.hash)) return;
          process.exitCode = 1
          console.log(colors.red(`Dead: ${result.link}`))
          return;
      }

      if (result.link.match(/^#/)) {
          if (markdownToc.includes(result.link)) {
              result.status = 'alive'
          } else {
              result.status = 'dead'
              result.statusCode = 0
          }
      }

      if (result.status === 'dead') {
        if (result.statusCode === 500) {
          console.log(colors.yellow(`Server error on target: ${result.link}`))
        } else {
          process.exitCode = 1
          console.log(colors.red(`Dead: ${result.link}`))
        }
      } else if (result.status == 'error') {
          process.exitCode = 1
          console.log(colors.red(`Error: ${result.link}`))
      }
    })
  })
})
<commit_msg>Fix style issues<commit_after>'use strict'

var colors = require('colors/safe')
var fs = require('fs')
var glob = require('glob')
var toc = require('markdown-toc')
var urlModule = require('url')
var markdownLinkCheck = require('markdown-link-check')
var path = require('path')

var files = glob.sync('**/*.md', { ignore: ['node_modules/**/*.md'] })

var tocCache = new Map()

function getToc (file) {
  file = path.normalize(file)
  if (tocCache.has(file)) {
    return tocCache.get(file)
  } else {
    var result = toc(fs.readFileSync(file).toString()).content
    tocCache.set(file, result)
    return result
  }
}

files.forEach(function (file) {
  var markdown = fs.readFileSync(file).toString()

  markdownLinkCheck(markdown, {
    baseUrl: path.basename(__dirname) + '/'
  }, function (err, results) {
    if (err) {
      console.error('Error', err)
      return
    }

    console.log('Reading: ' + file)

    // Get a list of all headers so we can verify intra-document links.
    var markdownToc = getToc(file)

    results.forEach(function (result) {
      var url = new URL(result.link, urlModule.pathToFileURL(file))
      if (url.protocol === 'file:' && !result.link.match(/ \(.*\)$/)) {
        var target = urlModule.fileURLToPath(url)
        if (!fs.existsSync(target)) {
          process.exitCode = 1
          console.log(colors.red(`Missing file: ${result.link}`))
          return
        }

        if (url.hash === '') return
        var toc = getToc(target)

        if (toc.includes(url.hash)) return
        process.exitCode = 1
        console.log(colors.red(`Dead: ${result.link}`))
        return
      }

      if (result.link.match(/^#/)) {
        if (markdownToc.includes(result.link)) {
          result.status = 'alive'
        } else {
          result.status = 'dead'
          result.statusCode = 0
        }
      }

      if (result.status === 'dead') {
        if (result.statusCode === 500) {
          console.log(colors.yellow(`Server error on target: ${result.link}`))
        } else {
          process.exitCode = 1
          console.log(colors.red(`Dead: ${result.link}`))
        }
      } else if (result.status === 'error') {
        process.exitCode = 1
        console.log(colors.red(`Error: ${result.link}`))
      }
    })
  })
})
<|endoftext|>


<commit_before>// Copyright 2016, University of Colorado Boulder

/**
 * IO type for JS's built-in number type.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var assertTypeOf = require( 'PHET_IO/assertions/assertTypeOf' );
  var phetioNamespace = require( 'PHET_IO/phetioNamespace' );
  var phetioInherit = require( 'PHET_IO/phetioInherit' );
  var TObject = require( 'PHET_IO/types/TObject' );

  // valid values for options.units
  var VALID_UNITS = [
    'amperes',
    'milliamperes',
    'becquerels',
    'centimeters',
    'centimeters-squared',
    'coulombs',
    'degrees Celsius',
    'farads',
    'kilograms',
    'grams',
    'gray',
    'henrys',
    'henries',
    'hertz',
    'joules',
    'katals',
    'kelvins',
    'liters',
    'liters/second',
    'lumens',
    'lux',
    'meters',
    'meters/second',
    'meters/second/second',
    'moles',
    'moles/liter',
    'nanometers',
    'newtons',
    'newtons/meters',
    'newtons-second/meters',
    'ohms',
    'ohm-centimeters',
    'pascals',
    'percent',
    'radians',
    'radians/second',
    'seconds',
    'siemens',
    'sieverts',
    'steradians',
    'tesla',
    'unitless',
    'volts',
    'watts',
    'webers'
  ];

  var TNumber = function( units, options ) {
    assert && assert( units, 'All TNumbers should specify units' );
    assert && assert( validUnits.indexOf( units ) >= 0, units + ' is not recognized as a valid unit of measurement' );

    options = _.extend( {
        type: 'FloatingPoint', // either 'FloatingPoint' | 'Integer'
        range: new RangeWithValue( -Infinity, Infinity ),
        stepSize: null, // This will be used for slider increments

        // TODO: enforce that values is of Array type
        values: null // null | {Number[]} if it can only take certain possible values, specify them here, like [0,2,8]
      },
      options
    );
    return phetioInherit( TObject, 'TNumber(' + units + ')', function( instance, phetioID ) {
      TObject.call( this, instance, phetioID );
      assertTypeOf( instance, 'number' );
    }, {}, {
      apiElements: { // named differently than api while it means type composite, see phetioInherit.js
        units: units,
        type: options.type,
        range: options.range,
        values: options.values
      },
      documentation: 'Wrapper for the built-in JS number type (floating point, but also represents integers)',

      fromStateObject: function( stateObject ) {
        return stateObject;
      },

      toStateObject: function( value ) {
        return value;
      },

      getAPI: function() {
        return { // named differently than api while it means type composite, see phetioInherit.js
          units: options.units,
          type: options.type,
          range: options.range,
          values: options.values
        };
      }
    } );
  }

  phetioNamespace.register( 'TNumber', TNumber );

  return TNumber;
} );<commit_msg>move NumberIO from phet-io after patches didn't apply, https://github.com/phetsims/phet-io/issues/1396<commit_after>// Copyright 2016, University of Colorado Boulder

/**
 * IO type for JS's built-in number type.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var phetioInherit = require( 'PHET_IO/phetioInherit' );
  var phetioNamespace = require( 'PHET_IO/phetioNamespace' );
  var ObjectIO = require( 'PHET_IO/types/ObjectIO' );

  /**
   * @constructor
   */
  function NumberIO() {
    assert && assert( false, 'should never be called' );
  }

  phetioNamespace.register( 'NumberIO', NumberIO );

  return phetioInherit( ObjectIO, 'NumberIO', NumberIO, {}, {
    documentation: 'Wrapper for the built-in JS number type (floating point, but also represents integers)',

    /**
     * Encodes a number to a state (which also happens to be a number).
     * @param {Object} value
     * @returns {Object}
     * @override
     */
    toStateObject: function( value ) {
      assert && assert( typeof value === 'number', 'value should be number' );
      if ( value === Number.POSITIVE_INFINITY ) {
        return 'POSITIVE_INFINITY';
      }
      else if ( value === Number.NEGATIVE_INFINITY ) {
        return 'NEGATIVE_INFINITY';
      }
      return value;
    },

    /**
     * Decode a number from a state, which is already a number.
     * @param {Object} stateObject
     * @returns {Object}
     * @override
     */
    fromStateObject: function( stateObject ) {
      if ( stateObject === 'POSITIVE_INFINITY' ) {
        return Number.POSITIVE_INFINITY;
      }
      else if ( stateObject === 'NEGATIVE_INFINITY' ) {
        return Number.NEGATIVE_INFINITY;
      }
      return stateObject;
    }
  } );
} );<|endoftext|>


<commit_before>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length < 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<commit_msg>🤖(break): 2017-6-13 20:33:23<commit_after>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length > 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<|endoftext|>


<commit_before>// Copyright 2016-2018, University of Colorado Boulder

/**
 * ObjectIO is the root of the IO Type hierarchy.  All IO types extend from ObjectIO.  This type can be subtyped or
 * used directly for types that only need toStateObject/fromStateObject.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var phetioInherit = require( 'TANDEM/phetioInherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var validate = require( 'AXON/validate' );

  /**
   * Main constructor for ObjectIO base IO type.
   * @param {Object} instance
   * @param {string} phetioID
   * @constructor
   * @abstract
   */
  function ObjectIO( instance, phetioID ) {
    assert && assert( instance, 'instance should be truthy' );
    assert && assert( phetioID, 'phetioID should be truthy' );

    // @public (read-only)
    this.instance = instance;

    // @public (read-only)
    this.phetioID = phetioID;

    // Use the validator defined on the constructor to make sure the instance is valid
    assert && validate( instance, this.constructor.validator );
  }

  // ObjectIO inherits from window.Object because it starts with its prototype in phetioInherit.inheritBase
  // However, when serialized, the ObjectIO supertype is reported as null (not sent in the JSON).
  phetioInherit( window.Object, 'ObjectIO', ObjectIO, {}, {

    /**
     * Documentation that appears in PhET-iO Studio, supports HTML markup.
     * @public
     */
    documentation: 'The root of the wrapper object hierarchy.',

    /**
     * A validator object to be used to validate the core types that IOTypes wrap.
     * @type {ValidatorDef}
     * @public
     * @override
     */
    validator: { isValidValue: instance => instance !== null && typeof instance === 'object' },

    /**
     * Return the json that ObjectIO is wrapping.  This can be overridden by subclasses, or types can use ObjectIO type
     * directly to use this implementation.
     * @param {Object} o
     * @returns {Object}
     * @public
     */
    toStateObject: function( o ) {
      return o;
    },

    /**
     * Decodes the object from a state, used in phetio.setState.  This can be overridden by subclasses, or types can
     * use ObjectIO type directly to use this implementation.
     * @param {Object} o
     * @returns {Object}
     * @public
     */
    fromStateObject: function( o ) {
      return o;
    }
  } );

  tandemNamespace.register( 'ObjectIO', ObjectIO );

  return ObjectIO;
} );<commit_msg>remove todo about validators, #204<commit_after>// Copyright 2016-2018, University of Colorado Boulder

/**
 * ObjectIO is the root of the IO Type hierarchy.  All IO types extend from ObjectIO.  This type can be subtyped or
 * used directly for types that only need toStateObject/fromStateObject.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var phetioInherit = require( 'TANDEM/phetioInherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var validate = require( 'AXON/validate' );

  /**
   * Main constructor for ObjectIO base IO type.
   * @param {Object} instance
   * @param {string} phetioID
   * @constructor
   * @abstract
   */
  function ObjectIO( instance, phetioID ) {
    assert && assert( instance, 'instance should be truthy' );
    assert && assert( phetioID, 'phetioID should be truthy' );

    // @public (read-only)
    this.instance = instance;

    // @public (read-only)
    this.phetioID = phetioID;

    // Use the validator defined on the constructor to make sure the instance is valid
    validate( instance, this.constructor.validator );
  }

  // ObjectIO inherits from window.Object because it starts with its prototype in phetioInherit.inheritBase
  // However, when serialized, the ObjectIO supertype is reported as null (not sent in the JSON).
  phetioInherit( window.Object, 'ObjectIO', ObjectIO, {}, {

    /**
     * Documentation that appears in PhET-iO Studio, supports HTML markup.
     * @public
     */
    documentation: 'The root of the wrapper object hierarchy.',

    /**
     * A validator object to be used to validate the core types that IOTypes wrap.
     * @type {ValidatorDef}
     * @public
     * @override
     */
    validator: { isValidValue: instance => instance !== null && typeof instance === 'object' },

    /**
     * Return the json that ObjectIO is wrapping.  This can be overridden by subclasses, or types can use ObjectIO type
     * directly to use this implementation.
     * @param {Object} o
     * @returns {Object}
     * @public
     */
    toStateObject: function( o ) {
      return o;
    },

    /**
     * Decodes the object from a state, used in phetio.setState.  This can be overridden by subclasses, or types can
     * use ObjectIO type directly to use this implementation.
     * @param {Object} o
     * @returns {Object}
     * @public
     */
    fromStateObject: function( o ) {
      return o;
    }
  } );

  tandemNamespace.register( 'ObjectIO', ObjectIO );

  return ObjectIO;
} );<|endoftext|>


<commit_before>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length < 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<commit_msg>🤖(fix): 2017-12-4 02:02:03<commit_after>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length > 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<|endoftext|>


<commit_before>(function(window, document, ionic) {

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
    results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  var IOS = 'ios';
  var ANDROID = 'android';
  var WINDOWS_PHONE = 'windowsphone';
  var requestAnimationFrame = ionic.requestAnimationFrame;

  /**
   * @ngdoc utility
   * @name ionic.Platform
   * @module ionic
   * @description
   * A set of utility methods that can be used to retrieve the device ready state and
   * various other information such as what kind of platform the app is currently installed on.
   *
   * @usage
   * ```js
   * angular.module('PlatformApp', ['ionic'])
   * .controller('PlatformCtrl', function($scope) {
   *
   *   ionic.Platform.ready(function(){
   *     // will execute when device is ready, or immediately if the device is already ready.
   *   });
   *
   *   var deviceInformation = ionic.Platform.device();
   *
   *   var isWebView = ionic.Platform.isWebView();
   *   var isIPad = ionic.Platform.isIPad();
   *   var isIOS = ionic.Platform.isIOS();
   *   var isAndroid = ionic.Platform.isAndroid();
   *   var isWindowsPhone = ionic.Platform.isWindowsPhone();
   *
   *   var currentPlatform = ionic.Platform.platform();
   *   var currentPlatformVersion = ionic.Platform.version();
   *
   *   ionic.Platform.exit(); // stops the app
   * });
   * ```
   */
  var self = ionic.Platform = {

    // Put navigator on platform so it can be mocked and set
    // the browser does not allow window.navigator to be set
    navigator: window.navigator,

    /**
     * @ngdoc property
     * @name ionic.Platform#isReady
     * @returns {boolean} Whether the device is ready.
     */
    isReady: false,
    /**
     * @ngdoc property
     * @name ionic.Platform#isFullScreen
     * @returns {boolean} Whether the device is fullscreen.
     */
    isFullScreen: false,
    /**
     * @ngdoc property
     * @name ionic.Platform#platforms
     * @returns {Array(string)} An array of all platforms found.
     */
    platforms: null,
    /**
     * @ngdoc property
     * @name ionic.Platform#grade
     * @returns {string} What grade the current platform is.
     */
    grade: null,
    ua: navigator.userAgent,

    /**
     * @ngdoc method
     * @name ionic.Platform#ready
     * @description
     * Trigger a callback once the device is ready, or immediately
     * if the device is already ready. This method can be run from
     * anywhere and does not need to be wrapped by any additonal methods.
     * When the app is within a WebView (Cordova), it'll fire
     * the callback once the device is ready. If the app is within
     * a web browser, it'll fire the callback after `window.load`.
     * Please remember that Cordova features (Camera, FileSystem, etc) still
     * will not work in a web browser.
     * @param {function} callback The function to call.
     */
    ready: function(cb) {
      // run through tasks to complete now that the device is ready
      if (self.isReady) {
        cb();
      } else {
        // the platform isn't ready yet, add it to this array
        // which will be called once the platform is ready
        readyCallbacks.push(cb);
      }
    },

    /**
     * @private
     */
    detect: function() {
      self._checkPlatforms();

      requestAnimationFrame(function() {
        // only add to the body class if we got platform info
        for (var i = 0; i < self.platforms.length; i++) {
          document.body.classList.add('platform-' + self.platforms[i]);
        }
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#setGrade
     * @description Set the grade of the device: 'a', 'b', or 'c'. 'a' is the best
     * (most css features enabled), 'c' is the worst.  By default, sets the grade
     * depending on the current device.
     * @param {string} grade The new grade to set.
     */
    setGrade: function(grade) {
      var oldGrade = self.grade;
      self.grade = grade;
      requestAnimationFrame(function() {
        if (oldGrade) {
          document.body.classList.remove('grade-' + oldGrade);
        }
        document.body.classList.add('grade-' + grade);
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#device
     * @description Return the current device (given by cordova).
     * @returns {object} The device object.
     */
    device: function() {
      return window.device || {};
    },

    _checkPlatforms: function() {
      self.platforms = [];
      var grade = 'a';

      if (self.isWebView()) {
        self.platforms.push('webview');
        self.platforms.push('cordova');
      } else {
        self.platforms.push('browser');
      }
      if (self.isIPad()) self.platforms.push('ipad');

      var platform = self.platform();
      if (platform) {
        self.platforms.push(platform);

        var version = self.version();
        if (version) {
          var v = version.toString();
          if (v.indexOf('.') > 0) {
            v = v.replace('.', '_');
          } else {
            v += '_0';
          }
          self.platforms.push(platform + v.split('_')[0]);
          self.platforms.push(platform + v);

          if (self.isAndroid() && version < 4.4) {
            grade = (version < 4 ? 'c' : 'b');
          } else if (self.isWindowsPhone()) {
            grade = 'b';
          }
        }
      }

      self.setGrade(grade);
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#isWebView
     * @returns {boolean} Check if we are running within a WebView (such as Cordova).
     */
    isWebView: function() {
      return !(!window.cordova && !window.PhoneGap && !window.phonegap);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isIPad
     * @returns {boolean} Whether we are running on iPad.
     */
    isIPad: function() {
      if (/iPad/i.test(self.navigator.platform)) {
        return true;
      }
      return /iPad/i.test(self.ua);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isIOS
     * @returns {boolean} Whether we are running on iOS.
     */
    isIOS: function() {
      return self.is(IOS);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isAndroid
     * @returns {boolean} Whether we are running on Android.
     */
    isAndroid: function() {
      return self.is(ANDROID);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isWindowsPhone
     * @returns {boolean} Whether we are running on Windows Phone.
     */
    isWindowsPhone: function() {
      return self.is(WINDOWS_PHONE);
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#platform
     * @returns {string} The name of the current platform.
     */
    platform: function() {
      // singleton to get the platform name
      if (platformName === null) self.setPlatform(self.device().platform);
      return platformName;
    },

    /**
     * @private
     */
    setPlatform: function(n) {
      if (typeof n != 'undefined' && n !== null && n.length) {
        platformName = n.toLowerCase();
      } else if (getParameterByName('ionicplatform')) {
        platformName = getParameterByName('ionicplatform');
      } else if (self.ua.indexOf('Android') > 0) {
        platformName = ANDROID;
      } else if (/iPhone|iPad|iPod/.test(self.ua)) {
        platformName = IOS;
      } else if (self.ua.indexOf('Windows Phone') > -1) {
        platformName = WINDOWS_PHONE;
      } else {
        platformName = self.navigator.platform && navigator.platform.toLowerCase().split(' ')[0] || '';
      }
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#version
     * @returns {number} The version of the current device platform.
     */
    version: function() {
      // singleton to get the platform version
      if (platformVersion === null) self.setVersion(self.device().version);
      return platformVersion;
    },

    /**
     * @private
     */
    setVersion: function(v) {
      if (typeof v != 'undefined' && v !== null) {
        v = v.split('.');
        v = parseFloat(v[0] + '.' + (v.length > 1 ? v[1] : 0));
        if (!isNaN(v)) {
          platformVersion = v;
          return;
        }
      }

      platformVersion = 0;

      // fallback to user-agent checking
      var pName = self.platform();
      var versionMatch = {
        'android': /Android (\d+).(\d+)?/,
        'ios': /OS (\d+)_(\d+)?/,
        'windowsphone': /Windows Phone (\d+).(\d+)?/
      };
      if (versionMatch[pName]) {
        v = self.ua.match(versionMatch[pName]);
        if (v &&  v.length > 2) {
          platformVersion = parseFloat(v[1] + '.' + v[2]);
        }
      }
    },

    // Check if the platform is the one detected by cordova
    is: function(type) {
      type = type.toLowerCase();
      // check if it has an array of platforms
      if (self.platforms) {
        for (var x = 0; x < self.platforms.length; x++) {
          if (self.platforms[x] === type) return true;
        }
      }
      // exact match
      var pName = self.platform();
      if (pName) {
        return pName === type.toLowerCase();
      }

      // A quick hack for to check userAgent
      return self.ua.toLowerCase().indexOf(type) >= 0;
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#exitApp
     * @description Exit the app.
     */
    exitApp: function() {
      self.ready(function() {
        navigator.app && navigator.app.exitApp && navigator.app.exitApp();
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#showStatusBar
     * @description Shows or hides the device status bar (in Cordova). Requires `cordova plugin add org.apache.cordova.statusbar`
     * @param {boolean} shouldShow Whether or not to show the status bar.
     */
    showStatusBar: function(val) {
      // Only useful when run within cordova
      self._showStatusBar = val;
      self.ready(function() {
        // run this only when or if the platform (cordova) is ready
        requestAnimationFrame(function() {
          if (self._showStatusBar) {
            // they do not want it to be full screen
            window.StatusBar && window.StatusBar.show();
            document.body.classList.remove('status-bar-hide');
          } else {
            // it should be full screen
            window.StatusBar && window.StatusBar.hide();
            document.body.classList.add('status-bar-hide');
          }
        });
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#fullScreen
     * @description
     * Sets whether the app is fullscreen or not (in Cordova).
     * @param {boolean=} showFullScreen Whether or not to set the app to fullscreen. Defaults to true. Requires `cordova plugin add org.apache.cordova.statusbar`
     * @param {boolean=} showStatusBar Whether or not to show the device's status bar. Defaults to false.
     */
    fullScreen: function(showFullScreen, showStatusBar) {
      // showFullScreen: default is true if no param provided
      self.isFullScreen = (showFullScreen !== false);

      // add/remove the fullscreen classname to the body
      ionic.DomUtil.ready(function() {
        // run this only when or if the DOM is ready
        requestAnimationFrame(function() {
          // fixing pane height before we adjust this
          var panes = document.getElementsByClassName('pane');
          for (var i = 0; i < panes.length; i++) {
            panes[i].style.height = panes[i].offsetHeight + "px";
          }
          if (self.isFullScreen) {
            document.body.classList.add('fullscreen');
          } else {
            document.body.classList.remove('fullscreen');
          }
        });
        // showStatusBar: default is false if no param provided
        self.showStatusBar((showStatusBar === true));
      });
    }

  };

  var platformName = null, // just the name, like iOS or Android
  platformVersion = null, // a float of the major and minor, like 7.1
  readyCallbacks = [],
  windowLoadListenderAttached;

  // setup listeners to know when the device is ready to go
  function onWindowLoad() {
    if (self.isWebView()) {
      // the window and scripts are fully loaded, and a cordova/phonegap
      // object exists then let's listen for the deviceready
      document.addEventListener("deviceready", onPlatformReady, false);
    } else {
      // the window and scripts are fully loaded, but the window object doesn't have the
      // cordova/phonegap object, so its just a browser, not a webview wrapped w/ cordova
      onPlatformReady();
    }
    if (windowLoadListenderAttached) {
      window.removeEventListener("load", onWindowLoad, false);
    }
  }
  if (document.readyState === 'complete') {
    onWindowLoad();
  } else {
    windowLoadListenderAttached = true;
    window.addEventListener("load", onWindowLoad, false);
  }

  function onPlatformReady() {
    // the device is all set to go, init our own stuff then fire off our event
    self.isReady = true;
    self.detect();
    for (var x = 0; x < readyCallbacks.length; x++) {
      // fire off all the callbacks that were added before the platform was ready
      readyCallbacks[x]();
    }
    readyCallbacks = [];
    ionic.trigger('platformready', { target: document });

    requestAnimationFrame(function() {
      document.body.classList.add('platform-ready');
    });
  }

})(this, document, ionic);
<commit_msg>fix(platform): revert b1f94da27e265ca32698b86785073d53208e6679, fixes #3175 #3279<commit_after>(function(window, document, ionic) {

  function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
    results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  var IOS = 'ios';
  var ANDROID = 'android';
  var WINDOWS_PHONE = 'windowsphone';
  var requestAnimationFrame = ionic.requestAnimationFrame;

  /**
   * @ngdoc utility
   * @name ionic.Platform
   * @module ionic
   * @description
   * A set of utility methods that can be used to retrieve the device ready state and
   * various other information such as what kind of platform the app is currently installed on.
   *
   * @usage
   * ```js
   * angular.module('PlatformApp', ['ionic'])
   * .controller('PlatformCtrl', function($scope) {
   *
   *   ionic.Platform.ready(function(){
   *     // will execute when device is ready, or immediately if the device is already ready.
   *   });
   *
   *   var deviceInformation = ionic.Platform.device();
   *
   *   var isWebView = ionic.Platform.isWebView();
   *   var isIPad = ionic.Platform.isIPad();
   *   var isIOS = ionic.Platform.isIOS();
   *   var isAndroid = ionic.Platform.isAndroid();
   *   var isWindowsPhone = ionic.Platform.isWindowsPhone();
   *
   *   var currentPlatform = ionic.Platform.platform();
   *   var currentPlatformVersion = ionic.Platform.version();
   *
   *   ionic.Platform.exit(); // stops the app
   * });
   * ```
   */
  var self = ionic.Platform = {

    // Put navigator on platform so it can be mocked and set
    // the browser does not allow window.navigator to be set
    navigator: window.navigator,

    /**
     * @ngdoc property
     * @name ionic.Platform#isReady
     * @returns {boolean} Whether the device is ready.
     */
    isReady: false,
    /**
     * @ngdoc property
     * @name ionic.Platform#isFullScreen
     * @returns {boolean} Whether the device is fullscreen.
     */
    isFullScreen: false,
    /**
     * @ngdoc property
     * @name ionic.Platform#platforms
     * @returns {Array(string)} An array of all platforms found.
     */
    platforms: null,
    /**
     * @ngdoc property
     * @name ionic.Platform#grade
     * @returns {string} What grade the current platform is.
     */
    grade: null,
    ua: navigator.userAgent,

    /**
     * @ngdoc method
     * @name ionic.Platform#ready
     * @description
     * Trigger a callback once the device is ready, or immediately
     * if the device is already ready. This method can be run from
     * anywhere and does not need to be wrapped by any additonal methods.
     * When the app is within a WebView (Cordova), it'll fire
     * the callback once the device is ready. If the app is within
     * a web browser, it'll fire the callback after `window.load`.
     * Please remember that Cordova features (Camera, FileSystem, etc) still
     * will not work in a web browser.
     * @param {function} callback The function to call.
     */
    ready: function(cb) {
      // run through tasks to complete now that the device is ready
      if (self.isReady) {
        cb();
      } else {
        // the platform isn't ready yet, add it to this array
        // which will be called once the platform is ready
        readyCallbacks.push(cb);
      }
    },

    /**
     * @private
     */
    detect: function() {
      self._checkPlatforms();

      requestAnimationFrame(function() {
        // only add to the body class if we got platform info
        for (var i = 0; i < self.platforms.length; i++) {
          document.body.classList.add('platform-' + self.platforms[i]);
        }
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#setGrade
     * @description Set the grade of the device: 'a', 'b', or 'c'. 'a' is the best
     * (most css features enabled), 'c' is the worst.  By default, sets the grade
     * depending on the current device.
     * @param {string} grade The new grade to set.
     */
    setGrade: function(grade) {
      var oldGrade = self.grade;
      self.grade = grade;
      requestAnimationFrame(function() {
        if (oldGrade) {
          document.body.classList.remove('grade-' + oldGrade);
        }
        document.body.classList.add('grade-' + grade);
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#device
     * @description Return the current device (given by cordova).
     * @returns {object} The device object.
     */
    device: function() {
      return window.device || {};
    },

    _checkPlatforms: function() {
      self.platforms = [];
      var grade = 'a';

      if (self.isWebView()) {
        self.platforms.push('webview');
        self.platforms.push('cordova');
      } else {
        self.platforms.push('browser');
      }
      if (self.isIPad()) self.platforms.push('ipad');

      var platform = self.platform();
      if (platform) {
        self.platforms.push(platform);

        var version = self.version();
        if (version) {
          var v = version.toString();
          if (v.indexOf('.') > 0) {
            v = v.replace('.', '_');
          } else {
            v += '_0';
          }
          self.platforms.push(platform + v.split('_')[0]);
          self.platforms.push(platform + v);

          if (self.isAndroid() && version < 4.4) {
            grade = (version < 4 ? 'c' : 'b');
          } else if (self.isWindowsPhone()) {
            grade = 'b';
          }
        }
      }

      self.setGrade(grade);
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#isWebView
     * @returns {boolean} Check if we are running within a WebView (such as Cordova).
     */
    isWebView: function() {
      return !(!window.cordova && !window.PhoneGap && !window.phonegap);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isIPad
     * @returns {boolean} Whether we are running on iPad.
     */
    isIPad: function() {
      if (/iPad/i.test(self.navigator.platform)) {
        return true;
      }
      return /iPad/i.test(self.ua);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isIOS
     * @returns {boolean} Whether we are running on iOS.
     */
    isIOS: function() {
      return self.is(IOS);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isAndroid
     * @returns {boolean} Whether we are running on Android.
     */
    isAndroid: function() {
      return self.is(ANDROID);
    },
    /**
     * @ngdoc method
     * @name ionic.Platform#isWindowsPhone
     * @returns {boolean} Whether we are running on Windows Phone.
     */
    isWindowsPhone: function() {
      return self.is(WINDOWS_PHONE);
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#platform
     * @returns {string} The name of the current platform.
     */
    platform: function() {
      // singleton to get the platform name
      if (platformName === null) self.setPlatform(self.device().platform);
      return platformName;
    },

    /**
     * @private
     */
    setPlatform: function(n) {
      if (typeof n != 'undefined' && n !== null && n.length) {
        platformName = n.toLowerCase();
      } else if (getParameterByName('ionicplatform')) {
        platformName = getParameterByName('ionicplatform');
      } else if (self.ua.indexOf('Android') > 0) {
        platformName = ANDROID;
      } else if (/iPhone|iPad|iPod/.test(self.ua)) {
        platformName = IOS;
      } else if (self.ua.indexOf('Windows Phone') > -1) {
        platformName = WINDOWS_PHONE;
      } else {
        platformName = self.navigator.platform && navigator.platform.toLowerCase().split(' ')[0] || '';
      }
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#version
     * @returns {number} The version of the current device platform.
     */
    version: function() {
      // singleton to get the platform version
      if (platformVersion === null) self.setVersion(self.device().version);
      return platformVersion;
    },

    /**
     * @private
     */
    setVersion: function(v) {
      if (typeof v != 'undefined' && v !== null) {
        v = v.split('.');
        v = parseFloat(v[0] + '.' + (v.length > 1 ? v[1] : 0));
        if (!isNaN(v)) {
          platformVersion = v;
          return;
        }
      }

      platformVersion = 0;

      // fallback to user-agent checking
      var pName = self.platform();
      var versionMatch = {
        'android': /Android (\d+).(\d+)?/,
        'ios': /OS (\d+)_(\d+)?/,
        'windowsphone': /Windows Phone (\d+).(\d+)?/
      };
      if (versionMatch[pName]) {
        v = self.ua.match(versionMatch[pName]);
        if (v &&  v.length > 2) {
          platformVersion = parseFloat(v[1] + '.' + v[2]);
        }
      }
    },

    // Check if the platform is the one detected by cordova
    is: function(type) {
      type = type.toLowerCase();
      // check if it has an array of platforms
      if (self.platforms) {
        for (var x = 0; x < self.platforms.length; x++) {
          if (self.platforms[x] === type) return true;
        }
      }
      // exact match
      var pName = self.platform();
      if (pName) {
        return pName === type.toLowerCase();
      }

      // A quick hack for to check userAgent
      return self.ua.toLowerCase().indexOf(type) >= 0;
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#exitApp
     * @description Exit the app.
     */
    exitApp: function() {
      self.ready(function() {
        navigator.app && navigator.app.exitApp && navigator.app.exitApp();
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#showStatusBar
     * @description Shows or hides the device status bar (in Cordova). Requires `cordova plugin add org.apache.cordova.statusbar`
     * @param {boolean} shouldShow Whether or not to show the status bar.
     */
    showStatusBar: function(val) {
      // Only useful when run within cordova
      self._showStatusBar = val;
      self.ready(function() {
        // run this only when or if the platform (cordova) is ready
        requestAnimationFrame(function() {
          if (self._showStatusBar) {
            // they do not want it to be full screen
            window.StatusBar && window.StatusBar.show();
            document.body.classList.remove('status-bar-hide');
          } else {
            // it should be full screen
            window.StatusBar && window.StatusBar.hide();
            document.body.classList.add('status-bar-hide');
          }
        });
      });
    },

    /**
     * @ngdoc method
     * @name ionic.Platform#fullScreen
     * @description
     * Sets whether the app is fullscreen or not (in Cordova).
     * @param {boolean=} showFullScreen Whether or not to set the app to fullscreen. Defaults to true. Requires `cordova plugin add org.apache.cordova.statusbar`
     * @param {boolean=} showStatusBar Whether or not to show the device's status bar. Defaults to false.
     */
    fullScreen: function(showFullScreen, showStatusBar) {
      // showFullScreen: default is true if no param provided
      self.isFullScreen = (showFullScreen !== false);

      // add/remove the fullscreen classname to the body
      ionic.DomUtil.ready(function() {
        // run this only when or if the DOM is ready
        requestAnimationFrame(function() {
          if (self.isFullScreen) {
            document.body.classList.add('fullscreen');
          } else {
            document.body.classList.remove('fullscreen');
          }
        });
        // showStatusBar: default is false if no param provided
        self.showStatusBar((showStatusBar === true));
      });
    }

  };

  var platformName = null, // just the name, like iOS or Android
  platformVersion = null, // a float of the major and minor, like 7.1
  readyCallbacks = [],
  windowLoadListenderAttached;

  // setup listeners to know when the device is ready to go
  function onWindowLoad() {
    if (self.isWebView()) {
      // the window and scripts are fully loaded, and a cordova/phonegap
      // object exists then let's listen for the deviceready
      document.addEventListener("deviceready", onPlatformReady, false);
    } else {
      // the window and scripts are fully loaded, but the window object doesn't have the
      // cordova/phonegap object, so its just a browser, not a webview wrapped w/ cordova
      onPlatformReady();
    }
    if (windowLoadListenderAttached) {
      window.removeEventListener("load", onWindowLoad, false);
    }
  }
  if (document.readyState === 'complete') {
    onWindowLoad();
  } else {
    windowLoadListenderAttached = true;
    window.addEventListener("load", onWindowLoad, false);
  }

  function onPlatformReady() {
    // the device is all set to go, init our own stuff then fire off our event
    self.isReady = true;
    self.detect();
    for (var x = 0; x < readyCallbacks.length; x++) {
      // fire off all the callbacks that were added before the platform was ready
      readyCallbacks[x]();
    }
    readyCallbacks = [];
    ionic.trigger('platformready', { target: document });

    requestAnimationFrame(function() {
      document.body.classList.add('platform-ready');
    });
  }

})(this, document, ionic);
<|endoftext|>


<commit_before>const tape = require('tape')
const wrappedMethods = require('./methods')

let tapeMock = (arg0, arg1, cb) => {
  cb = cb || arg1 || arg0 // `arg0` and `arg1` are optional in `tape`
  let res = cb(testObjectMock)
  return [arg0, arg1, res]
}
let testObjectMock = { end: function () {} }
wrappedMethods.forEach(elem => {
  testObjectMock[elem] = function () { return arguments }
})
global.flipTape = { tapeMock }
let flippedTape = require('.')

tape('`String.prototype.test(cb)`', t => {
  t.plan(2)
  let cbMock = tapeObject => tapeObject
  let testOpts = {test: 123}

  t.equal(typeof ''.test, 'function', '`.test` function is attached to `String.prototype` before the first call to `flip-tape`')

  let result = 'msg'.test(testOpts, cbMock)
  t.deepEqual(result, tapeMock('msg', testOpts, cbMock), 'arguments are passed on')
})

flippedTape(x => {
  var arityToMethod = {
    1: ['fail', 'pass', 'skip'],
    2: ['ok', 'notOk', 'error'],
    3: ['equal', 'notEqual', 'deepEqual', 'notDeepEqual', 'deepLooseEqual', 'notDeepLooseEqual', 'throws', 'doesNotThrow', 'comment']
  }

  tape('`String.prototype.t(cb)`', t => {
    t.plan(2)

    t.equal(typeof ''.t, 'function', '`.t` function is attached to `String.prototype`')

    let cbArgument = null
    let cbMock = t => { cbArgument = t }
    'msg'.t(cbMock)
    t.deepEqual(cbArgument, testObjectMock, 'test object is passed on to cb')
  })

  Object.keys(arityToMethod).forEach(arity => {
    arity = +arity
    arityToMethod[arity].forEach(methodName => {
      let args = callMethod(methodName, arity)

      tape('`String.prototype.' + methodName + '()`', t => {
        t.plan(arity + 1)

        t.equal(typeof ''.t, 'function', '`.' + methodName + '` function is attached to `String.prototype`')

        if (arity === 3) {
          t.equal(args[1].toString(), 'arg1', 'second argument is passed on')
        }

        if ([2, 3].includes(arity)) {
          t.equal(args[0].toString(), 'arg0', 'first argument is passed on')
        }

        t.equal(args[arity - 1].toString(), 'msg', 'message argument is passed on')
      })
    })
  })
})

function callMethod (method, arity) {
  if (arity === 3) return 'msg'[method]('arg0', 'arg1')
  if (arity === 2) return 'msg'[method]('arg0')
  return 'msg'[method]()
}
<commit_msg>+ smoke test<commit_after>const tape = require('tape')
const wrappedMethods = require('./methods')
const exec = require('child_process').exec

let tapeMock = (arg0, arg1, cb) => {
  cb = cb || arg1 || arg0 // `arg0` and `arg1` are optional in `tape`
  let res = cb(testObjectMock)
  return [arg0, arg1, res]
}
let testObjectMock = { end: function () {} }
wrappedMethods.forEach(elem => {
  testObjectMock[elem] = function () { return arguments }
})
global.flipTape = { tapeMock }
let flippedTape = require('.')

tape('smoke test', t => {
  t.plan(1)
  exec('node example.js', {}, (err, _, stderr) => {
    t.ok(!err && !stderr, 'example.js terminated ok')
  })
})

tape('`String.prototype.test(cb)`', t => {
  t.plan(2)
  let cbMock = tapeObject => tapeObject
  let testOpts = {test: 123}

  t.equal(typeof ''.test, 'function', '`.test` function is attached to `String.prototype` before the first call to `flip-tape`')

  let result = 'msg'.test(testOpts, cbMock)
  t.deepEqual(result, tapeMock('msg', testOpts, cbMock), 'arguments are passed on')
})

flippedTape(x => {
  var arityToMethod = {
    1: ['fail', 'pass', 'skip'],
    2: ['ok', 'notOk', 'error'],
    3: ['equal', 'notEqual', 'deepEqual', 'notDeepEqual', 'deepLooseEqual', 'notDeepLooseEqual', 'throws', 'doesNotThrow', 'comment']
  }

  tape('`String.prototype.t(cb)`', t => {
    t.plan(2)

    t.equal(typeof ''.t, 'function', '`.t` function is attached to `String.prototype`')

    let cbArgument = null
    let cbMock = t => { cbArgument = t }
    'msg'.t(cbMock)
    t.deepEqual(cbArgument, testObjectMock, 'test object is passed on to cb')
  })

  Object.keys(arityToMethod).forEach(arity => {
    arity = +arity
    arityToMethod[arity].forEach(methodName => {
      let args = callMethod(methodName, arity)

      tape('`String.prototype.' + methodName + '()`', t => {
        t.plan(arity + 1)

        t.equal(typeof ''.t, 'function', '`.' + methodName + '` function is attached to `String.prototype`')

        if (arity === 3) {
          t.equal(args[1].toString(), 'arg1', 'second argument is passed on')
        }

        if ([2, 3].includes(arity)) {
          t.equal(args[0].toString(), 'arg0', 'first argument is passed on')
        }

        t.equal(args[arity - 1].toString(), 'msg', 'message argument is passed on')
      })
    })
  })
})

function callMethod (method, arity) {
  if (arity === 3) return 'msg'[method]('arg0', 'arg1')
  if (arity === 2) return 'msg'[method]('arg0')
  return 'msg'[method]()
}
<|endoftext|>


<commit_before>const loaderUtils = require('loader-utils')
const cmlUtils = require('chameleon-tool-utils');
const { getScriptCode } = require('chameleon-loader/src/interface-check/getScriptCode.js');
const helper = require('./helper.js');

module.exports = function(source) {
  const self = this;
  const rawOptions = loaderUtils.getOptions(this) || {};
  const resourcePath = this.resourcePath;
  let {partType, cmlType, fileType, media, check} = rawOptions;
  const context = (
    this.rootContext ||
    (this.options && this.options.context) ||
    process.cwd()
  )
  let parts = cmlUtils.splitParts({content: source});
  this._module._nodeType = 'module';
  this._module._moduleType = partType;
  this._module._parentNodeType = fileType;

  let cmlInfo = this._compiler._mvvmCmlInfo[this.resourcePath];

  let output = '';
  switch (partType) {
    case 'style':
      output = parts.style[0].content; // 交给后面loader
      break;
    case 'script':
      parts.script.forEach(item => {  // 交给后面loader
        if (item.cmlType !== 'json') {
          let content = item.content;
          let {runtimeNpmName, runtimeNeedComponents} = this._compiler._platformPlugin;
          let insertMethodMap = {
            app: 'createApp',
            page: 'createPage',
            component: 'createComponent',
          }
          let runtimeScript = '';
          runtimeScript += `
          import ${helper.toUpperCase(runtimeNpmName)} from '${runtimeNpmName}';\n
          `
          // runtime方法需要组件
          if (runtimeNeedComponents) {
            let {componentFiles} = cmlInfo;
            let components = ['{'];
            let comKeys = Object.keys(componentFiles);
            comKeys.forEach((comName, index) => {
              content += `
              import ${helper.toUpperCase(comName)} from "${cmlUtils.handleRelativePath(self.resourcePath, componentFiles[comName])}"\n`;
              if (comKeys.length - 1 === index) {
                components.push(`${helper.toUpperCase(comName)}`);
              } else {
                components.push(`${helper.toUpperCase(comName)},`);
              }
            })

            components.push('}');

            runtimeScript += `
            ${helper.toUpperCase(runtimeNpmName)}.${insertMethodMap[fileType]}(exports.default, ${components.join('')});\n
            `
          } else {
            runtimeScript += `
            ${helper.toUpperCase(runtimeNpmName)}.${insertMethodMap[fileType]}(exports.default);\n
            `
          }

          content += runtimeScript;

          output = getScriptCode(self, cmlType, content, media, check);
        }
      })
      break;
    case 'template':
      this._module._cmlSource = cmlInfo.compiledTemplate || '';
      this._module._cmlExtra = {
        usingComponents: cmlInfo.usingComponents || [],
        currentUsedBuildInTagMap: cmlInfo.currentUsedBuildInTagMap || []
      }
      output = `module.exports = ${JSON.stringify(cmlInfo.compiledTemplate)}`;

      break;
    case 'json':
      this._module._cmlSource = JSON.stringify(cmlInfo.compiledJson || {}, '', 4);
      output = `module.exports = ${this._module._cmlSource}`;
      break;
    default:
      break;
  }
  return output;
}<commit_msg>getOptions<commit_after>const loaderUtils = require('loader-utils')
const cmlUtils = require('chameleon-tool-utils');
const { getScriptCode } = require('chameleon-loader/src/interface-check/getScriptCode.js');
const helper = require('./helper.js');

module.exports = function(source) {
  const self = this;
  const rawOptions = loaderUtils.getOptions(this) || {};
  const resourcePath = this.resourcePath;
  let {partType, cmlType, fileType, media, check} = rawOptions;
  const context = (
    this.rootContext ||
    (this.options && this.options.context) ||
    process.cwd()
  )
  let parts = cmlUtils.splitParts({content: source});
  this._module._nodeType = 'module';
  this._module._moduleType = partType;
  this._module._parentNodeType = fileType;

  let cmlInfo = this._compiler._mvvmCmlInfo[this.resourcePath];

  let output = '';
  switch (partType) {
    case 'style':
      output = parts.style[0].content; // 交给后面loader
      break;
    case 'script':
      parts.script.forEach(item => {  // 交给后面loader
        if (item.cmlType !== 'json') {
          let content = item.content;
          let {runtimeNpmName, runtimeNeedComponents} = this._compiler._platformPlugin;
          let insertMethodMap = {
            app: 'createApp',
            page: 'createPage',
            component: 'createComponent',
          }
          let runtimeScript = '';
          runtimeScript += `
          import ${helper.toUpperCase(runtimeNpmName)} from '${runtimeNpmName}';\n
          `
          // runtime方法需要组件
          if (runtimeNeedComponents) {
            let {componentFiles} = cmlInfo;
            let components = ['{'];
            let comKeys = Object.keys(componentFiles);
            comKeys.forEach((comName, index) => {
              content += `
              import ${helper.toUpperCase(comName)} from "${cmlUtils.handleRelativePath(self.resourcePath, componentFiles[comName])}"\n`;
              if (comKeys.length - 1 === index) {
                components.push(`${helper.toUpperCase(comName)}`);
              } else {
                components.push(`${helper.toUpperCase(comName)},`);
              }
            })

            components.push('}');

            runtimeScript += `
            exports.default = ${helper.toUpperCase(runtimeNpmName)}.${insertMethodMap[fileType]}(exports.default, ${components.join('')}).getOptions();\n
            `
          } else {
            runtimeScript += `
            exports.default = ${helper.toUpperCase(runtimeNpmName)}.${insertMethodMap[fileType]}(exports.default).getOptions();\n
            `
          }

          content += runtimeScript;

          output = getScriptCode(self, cmlType, content, media, check);
        }
      })
      break;
    case 'template':
      this._module._cmlSource = cmlInfo.compiledTemplate || '';
      this._module._cmlExtra = {
        usingComponents: cmlInfo.usingComponents || [],
        currentUsedBuildInTagMap: cmlInfo.currentUsedBuildInTagMap || []
      }
      output = `module.exports = ${JSON.stringify(cmlInfo.compiledTemplate)}`;

      break;
    case 'json':
      this._module._cmlSource = JSON.stringify(cmlInfo.compiledJson || {}, '', 4);
      output = `module.exports = ${this._module._cmlSource}`;
      break;
    default:
      break;
  }
  return output;
}<|endoftext|>