Тестовый шаг, выдающий ошибку: «объект int не имеет атрибута replace» - PullRequest
0 голосов
/ 15 апреля 2019

Я создаю приложение zapier через zapier-cli - у меня возникла проблема с действием create:

Вот код приложения:

const authentication = require('./authentication');
const response = require('./creates/response'); 
const workspace = require('./triggers/workspace');
const form = require('./triggers/form');

const includeAccessTokenHeader = (request, z, bundle) => {
  if(bundle.authData.access_token) {
    request.headers = request.headers || {};
    request.headers['Authorization'] = `Bearer ${bundle.authData.access_token}`
  }
}

const tokenRefreshIf401 = (response, z, bundle) => {
  if(bundle.authData.access_token) {
    if(response.status === 401) {
      throw new z.errors.RefreshAuthError('Access token needs refreshing');
    }
  }
  return response;
}

// We can roll up all our behaviors in an App.
const App = {
  // This is just shorthand to reference the installed dependencies you have. Zapier will
  // need to know these before we can upload
  version: require('./package.json').version,
  platformVersion: require('zapier-platform-core').version,

  authentication: authentication,

  // beforeRequest & afterResponse are optional hooks into the provided HTTP client
  beforeRequest: [
    //includeAccessTokenHeader
  ],

  afterResponse: [
    tokenRefreshIf401
  ],

  // If you want to define optional resources to simplify creation of triggers, searches, creates - do that here!
  resources: {
  },

  // If you want your trigger to show up, you better include it here!
  triggers: {
    [workspace.key]: workspace,
    [form.key]: form
  },

  // If you want your searches to show up, you better include it here!
  searches: {
  },

  // If you want your creates to show up, you better include it here!
  creates: {
    [response.key]: response
  }
};

// Finally, export the app.
module.exports = App;

Вот ответное действие:

const questionFields = require('../fields/questions');

const createResponse = (z, bundle) => {
  z.console.log("Final input to be sent", bundle.inputData);
  const options = {
    url: 'https://sametrica-zapier.free.beeceptor.com/my/api/path',
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'content-type': 'application/json',
      'Authorization': `Bearer ${bundle.authData.access_token}`
    },
    body: bundle.inputData
  }

  // You may return a promise or a normal data structure from any perform method.
  return z.request(options)
    .then((response) => {
      response.throwForStatus();
      return z.JSON.parse(response.content);
    });
};
// We recommend writing your creates separate like this and rolling them
// into the App definition at the end.
module.exports = {
  key: 'response',

  // You'll want to provide some helpful display labels and descriptions
  // for users. Zapier will put them into the UX.
  noun: 'Response',
  display: {
    label: 'Create Response',
    description: 'Creates a new response.'
  },

  // `operation` is where the business logic goes.
  operation: {
    inputFields: [
      { 
        key: 'workspace', 
        required: true,
        dynamic: 'get_workspaces.id.name',
        altersDynamicFields: true,
      },
      { 
        key: 'form', 
        required: true,
        dynamic: 'get_forms.id.title_en',
        altersDynamicFields: true,
      },
      questionFields.fetchQuestions
    ],
    perform: createResponse,

    // In cases where Zapier needs to show an example record to the user, but we are unable to get a live example
    // from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of
    // returned records, and have obviously dummy values that we can show to any user.
    sample: {
      id: 1,
      createdAt: 1472069465,
      name: 'Best Spagetti Ever',
      authorId: 1,
      directions: '1. Boil Noodles\n2.Serve with sauce',
      style: 'italian'
    },

    // If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom
    // field definitions. The result will be used to augment the sample.
    // outputFields: () => { return []; }
    // Alternatively, a static field definition should be provided, to specify labels for the fields
    outputFields: [
      {key: 'id', label: 'ID'},
      {key: 'createdAt', label: 'Created At'},
      {key: 'name', label: 'Name'},
      {key: 'directions', label: 'Directions'},
      {key: 'authorId', label: 'Author ID'},
      {key: 'style', label: 'Style'}
    ]
  }
};

Вот триггер вопросов:

const makeField = (question, z) => {
  let field = {
    key: question.id,
    label: question.title_en,
    required: (question.is_optional === 0),
  };
  return field;
  switch(question.question_type.type) {
    case 'multiple_fields':
      let newField = {
        key: question.id,
        label: question.title_en,
        //required: (question.is_optional === 0),
        children: makeMultipleFieldsField(question)
      };
      z.console.log("Multiple Field", newField);
      return newField;
      break;
    default:
      return field;
  }
};

const makeRadioField = (question) => {
  let choices = question.options.map(option => {
    return {
      key: option.id,
      label: option.title_en
    }
  });
  return {
    choices
  };
};

const makeMultipleFieldsField = (question) => {
  let children = question.options.map(option => {
    return {
      key: option.id,
      label: option.title_en
    }
  });
  return children;
}


const fetchQuestions = async function(z, bundle) {
  z.console.log("Check if inputData has form @ fetchQuestions", bundle.inputData);
  const options = {
    url: `http://my-endpoint.ca/api/forms/${bundle.inputData.form}/respond`,
    method: 'GET',
    headers: {
      'Accept': 'application/json',
      'content-type': 'application/json',
      'Authorization': `Bearer ${bundle.authData.access_token}`
    }
  }; // EO options

  let response = await z.request(options);
  response.throwForStatus();
  const result = z.JSON.parse(response.content);
  let fieldArray = [];
  // get pages
  const pages = result.pages;
  pages.forEach(function(page) {
    const sections = page.sections;
    sections.forEach(function(section) {
      const questions = section.questions;
      questions.forEach(function(question) {
        // fieldArray.push({
        //   key: question.id,
        //   label: question.title_en,
        //   type: 'string'
        // });
        let field = makeField(question, z);
        fieldArray.push(field);
      }); // EO forEach questions
    }); // EO forEach sections
  }); // EO forEach pages
  z.console.log("Fields Array", fieldArray);
  return fieldArray;
} // EO fetchForms()


module.exports = {
  makeField,

  makeRadioField,

  fetchQuestions
}

Я получаю ошибку:

'int' object has no attribute 'replace'
...