{"action":"created","comment":{"url":"https://api.github.com/repos/namely/connect/pulls/comments/35545194","id":35545194,"diff_hunk":"@@ -21,45 +22,160 @@\n       field_mappings = netsuite_attribute_mapper.field_mappings\n       export_profile_keys = field_mappings.map(&:integration_field_name)\n \n-      export_ready_profile = netsuite_attribute_mapper.call(profile)\n-\n-      expect(export_ready_profile.keys).to match_array(export_profile_keys)\n-    end\n-\n-    it \"sets expected values in the profile\" do\n-      export_ready_profile = netsuite_attribute_mapper.call(profile)\n+      export_attributes = netsuite_attribute_mapper.call(\n+        stubbed_profile(stubbed_profile_data)\n+      )\n \n-      expect(export_ready_profile.values).to match_array(profile.values)\n+      expect(\n+        export_attributes.keys.to_set\n+      ).to be_superset(export_profile_keys.to_set)\n     end\n \n     it \"doesn't map empty values\" do\n-      delete_keys = %w(email last_name)\n-      trimmed_profile = profile\n-      delete_keys.each { |key| trimmed_profile.delete(key) }\n+      delete_keys = [:email, :last_name]\n+      profile_data = stubbed_profile_data\n+      delete_keys.each { |key| profile_data.delete(key) }\n       field_mappings = netsuite_attribute_mapper.field_mappings\n       deleted_field_mappings = field_mappings.select do |mapping|\n-        delete_keys.member?(mapping.namely_field_name)\n+        delete_keys.member?(mapping.namely_field_name.to_sym)\n       end\n \n       deleted_import_fields = deleted_field_mappings.map(\n         &:integration_field_name\n       )\n \n-      export_ready_profile = netsuite_attribute_mapper.call(trimmed_profile)\n+      export_attributes = netsuite_attribute_mapper.call(\n+        stubbed_profile(profile_data)\n+      )\n \n       expect(deleted_import_fields.to_set).not_to be_subset(\n-        export_ready_profile.keys.to_set\n+        export_attributes.keys.to_set\n       )\n     end\n+\n+    describe \"value handling\" do\n+      it \"sets expected values in the profile for regular attributes\" do\n+        profile_data = stubbed_profile_with_fields(\n+          %w(email first_name home_phone last_name)\n+        )\n+\n+        export_attributes = netsuite_attribute_mapper.call(\n+          stubbed_profile(profile_data)\n+        )\n+\n+        expect(\n+          export_attributes.values.to_set\n+        ).to be_superset(profile_data.values.to_set)\n+      end\n+\n+      context \"gender mapping\" do\n+        it \"maps 'Female to _female'\" do\n+          profile_data = { \"gender\" => \"Female\" }\n+\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile(profile_data)\n+          )\n+\n+          expect(export_attributes[\"gender\"]).to eq(\"_female\")\n+        end\n+\n+        it \"maps 'Male to _male'\" do\n+          profile_data = { \"gender\" => \"Male\" }\n+\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile(profile_data)\n+          )\n+\n+          expect(export_attributes[\"gender\"]).to eq(\"_male\")\n+        end\n+\n+        it \"maps 'Not specified' to '_omitted'\" do\n+          profile_data = { \"gender\" => \"Not specified\" }\n+\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile(profile_data)\n+          )\n+\n+          expect(export_attributes[\"gender\"]).to eq(\"_omitted\")\n+        end\n+\n+        it \"maps nil to '_omitted'\" do\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile({})\n+          )\n+\n+          expect(export_attributes[\"gender\"]).to eq(\"_omitted\")\n+        end\n+\n+        it \"maps an empty string to '_omitted'\" do\n+          profile_data = { \"gender\" => \"\" }\n+\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile(profile_data)\n+          )\n+\n+          expect(export_attributes[\"gender\"]).to eq(\"_omitted\")\n+        end\n+      end\n+\n+      context \"job title\" do\n+        it \"extracts the job_title name\" do\n+          title = \"Robot\"\n+\n+          export_attributes = netsuite_attribute_mapper.call(\n+            stubbed_profile(stubbed_job_title(title))\n+          )\n+\n+          expect(export_attributes[\"title\"]).to eq(title)\n+        end\n+\n+        context \"nil value\" do\n+          it \"sets an empty string\" do\n+            export_attributes = netsuite_attribute_mapper.call(\n+              stubbed_profile({})\n+            )\n+\n+            expect(export_attributes[\"title\"]).to eq(\"\")\n+          end\n+        end\n+      end\n+\n+      context \"subsidiary_id\" do\n+        it \"provides a subsidiary_id from the configuration\" do\n+          export_attributes = netsuite_attribute_mapper.call(stubbed_profile)\n+\n+          expect(\n+            export_attributes[\"subsidiary\"]\n+          ).to eq(\"internalId\" => configuration.subsidiary_id)\n+        end\n+      end\n+    end\n+  end\n+\n+  def stubbed_profile_data\n+    {\n+      email: \"test@example.com\",\n+      first_name: \"First\",\n+      gender: \"Female\",\n+      home_phone: \"212-555-1212\",\n+      last_name: \"Last\"\n+    }.merge(stubbed_job_title(\"Robot\"))\n+  end\n+\n+  def stubbed_profile_with_fields(fields)\n+    stubbed_profile_data.select { |key, _| fields.member?(key) }\n   end\n \n-  def profile\n+  def stubbed_job_title(title)\n     {\n-      \"email\" => \"test@example.com\",\n-      \"first_name\" => \"First\",\n-      \"gender\" => \"female\",\n-      \"home_phone\" => \"212-555-1212\",\n-      \"last_name\" => \"Last\"\n+      job_title: {\n+        id: \"1234\",\n+        title: title\n+      }\n     }\n   end\n+\n+  def stubbed_profile(data = stubbed_profile_data)\n+    OpenStruct.new(data)","path":"spec/models/net_suite/attribute_mapper_spec.rb","position":193,"original_position":193,"commit_id":"2a9e9c323b9b4aa6a268f1ed4e3ce061d3b30d47","original_commit_id":"2a9e9c323b9b4aa6a268f1ed4e3ce061d3b30d47","user":{"login":"base10","id":26247,"avatar_url":"https://avatars.githubusercontent.com/u/26247?v=3","gravatar_id":"","url":"https://api.github.com/users/base10","html_url":"https://github.com/base10","followers_url":"https://api.github.com/users/base10/followers","following_url":"https://api.github.com/users/base10/following{/other_user}","gists_url":"https://api.github.com/users/base10/gists{/gist_id}","starred_url":"https://api.github.com/users/base10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/base10/subscriptions","organizations_url":"https://api.github.com/users/base10/orgs","repos_url":"https://api.github.com/users/base10/repos","events_url":"https://api.github.com/users/base10/events{/privacy}","received_events_url":"https://api.github.com/users/base10/received_events","type":"User","site_admin":false},"body":"Yeah, that seems fine.","created_at":"2015-07-27T15:00:20Z","updated_at":"2015-07-27T15:00:20Z","html_url":"https://github.com/namely/connect/pull/148#discussion_r35545194","pull_request_url":"https://api.github.com/repos/namely/connect/pulls/148","_links":{"self":{"href":"https://api.github.com/repos/namely/connect/pulls/comments/35545194"},"html":{"href":"https://github.com/namely/connect/pull/148#discussion_r35545194"},"pull_request":{"href":"https://api.github.com/repos/namely/connect/pulls/148"}}},"pull_request":{"url":"https://api.github.com/repos/namely/connect/pulls/148","id":40907716,"html_url":"https://github.com/namely/connect/pull/148","diff_url":"https://github.com/namely/connect/pull/148.diff","patch_url":"https://github.com/namely/connect/pull/148.patch","issue_url":"https://api.github.com/repos/namely/connect/issues/148","number":148,"state":"open","locked":false,"title":"NetSuite::AttributeMapper can provide export-ready attributes","user":{"login":"base10","id":26247,"avatar_url":"https://avatars.githubusercontent.com/u/26247?v=3","gravatar_id":"","url":"https://api.github.com/users/base10","html_url":"https://github.com/base10","followers_url":"https://api.github.com/users/base10/followers","following_url":"https://api.github.com/users/base10/following{/other_user}","gists_url":"https://api.github.com/users/base10/gists{/gist_id}","starred_url":"https://api.github.com/users/base10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/base10/subscriptions","organizations_url":"https://api.github.com/users/base10/orgs","repos_url":"https://api.github.com/users/base10/repos","events_url":"https://api.github.com/users/base10/events{/privacy}","received_events_url":"https://api.github.com/users/base10/received_events","type":"User","site_admin":false},"body":"* NetSuite::AttributeMapper will be passed as context to\n  ::AttributeMapper\n* NetSuite::AttributeMapper defines a hash in `#post_mapping_handlers`\n  * These will convert a matching value in the transformed profile to\n    what will be expected at NetSuite\n  * I didn't implement this as an `inject` since I'm not always\n    expecting to have a value in the transformed profile, but I want to\n    ensure one exists after post handling\n* This will need to be hooked into\n  `NetSuite::Export::Employee#attributes`\n* This will replace handling in NetSuite::Export for mapping gender,\n  handling the job title data structure and setting the subsidiary id\n* For: https://trello.com/c/at7jXc36/","created_at":"2015-07-27T14:17:19Z","updated_at":"2015-07-27T15:00:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b8cd698ace37013b3f4d82df45c9f8042e8ae111","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/namely/connect/pulls/148/commits","review_comments_url":"https://api.github.com/repos/namely/connect/pulls/148/comments","review_comment_url":"https://api.github.com/repos/namely/connect/pulls/comments{/number}","comments_url":"https://api.github.com/repos/namely/connect/issues/148/comments","statuses_url":"https://api.github.com/repos/namely/connect/statuses/2a9e9c323b9b4aa6a268f1ed4e3ce061d3b30d47","head":{"label":"namely:nlw-netsuite-export-with-netsuite-attribute-mapper","ref":"nlw-netsuite-export-with-netsuite-attribute-mapper","sha":"2a9e9c323b9b4aa6a268f1ed4e3ce061d3b30d47","user":{"login":"namely","id":1004321,"avatar_url":"https://avatars.githubusercontent.com/u/1004321?v=3","gravatar_id":"","url":"https://api.github.com/users/namely","html_url":"https://github.com/namely","followers_url":"https://api.github.com/users/namely/followers","following_url":"https://api.github.com/users/namely/following{/other_user}","gists_url":"https://api.github.com/users/namely/gists{/gist_id}","starred_url":"https://api.github.com/users/namely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/namely/subscriptions","organizations_url":"https://api.github.com/users/namely/orgs","repos_url":"https://api.github.com/users/namely/repos","events_url":"https://api.github.com/users/namely/events{/privacy}","received_events_url":"https://api.github.com/users/namely/received_events","type":"Organization","site_admin":false},"repo":{"id":26101808,"name":"connect","full_name":"namely/connect","owner":{"login":"namely","id":1004321,"avatar_url":"https://avatars.githubusercontent.com/u/1004321?v=3","gravatar_id":"","url":"https://api.github.com/users/namely","html_url":"https://github.com/namely","followers_url":"https://api.github.com/users/namely/followers","following_url":"https://api.github.com/users/namely/following{/other_user}","gists_url":"https://api.github.com/users/namely/gists{/gist_id}","starred_url":"https://api.github.com/users/namely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/namely/subscriptions","organizations_url":"https://api.github.com/users/namely/orgs","repos_url":"https://api.github.com/users/namely/repos","events_url":"https://api.github.com/users/namely/events{/privacy}","received_events_url":"https://api.github.com/users/namely/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/namely/connect","description":"Namely Connect – Integrations with the Namely HRIS System.","fork":false,"url":"https://api.github.com/repos/namely/connect","forks_url":"https://api.github.com/repos/namely/connect/forks","keys_url":"https://api.github.com/repos/namely/connect/keys{/key_id}","collaborators_url":"https://api.github.com/repos/namely/connect/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/namely/connect/teams","hooks_url":"https://api.github.com/repos/namely/connect/hooks","issue_events_url":"https://api.github.com/repos/namely/connect/issues/events{/number}","events_url":"https://api.github.com/repos/namely/connect/events","assignees_url":"https://api.github.com/repos/namely/connect/assignees{/user}","branches_url":"https://api.github.com/repos/namely/connect/branches{/branch}","tags_url":"https://api.github.com/repos/namely/connect/tags","blobs_url":"https://api.github.com/repos/namely/connect/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/namely/connect/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/namely/connect/git/refs{/sha}","trees_url":"https://api.github.com/repos/namely/connect/git/trees{/sha}","statuses_url":"https://api.github.com/repos/namely/connect/statuses/{sha}","languages_url":"https://api.github.com/repos/namely/connect/languages","stargazers_url":"https://api.github.com/repos/namely/connect/stargazers","contributors_url":"https://api.github.com/repos/namely/connect/contributors","subscribers_url":"https://api.github.com/repos/namely/connect/subscribers","subscription_url":"https://api.github.com/repos/namely/connect/subscription","commits_url":"https://api.github.com/repos/namely/connect/commits{/sha}","git_commits_url":"https://api.github.com/repos/namely/connect/git/commits{/sha}","comments_url":"https://api.github.com/repos/namely/connect/comments{/number}","issue_comment_url":"https://api.github.com/repos/namely/connect/issues/comments{/number}","contents_url":"https://api.github.com/repos/namely/connect/contents/{+path}","compare_url":"https://api.github.com/repos/namely/connect/compare/{base}...{head}","merges_url":"https://api.github.com/repos/namely/connect/merges","archive_url":"https://api.github.com/repos/namely/connect/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/namely/connect/downloads","issues_url":"https://api.github.com/repos/namely/connect/issues{/number}","pulls_url":"https://api.github.com/repos/namely/connect/pulls{/number}","milestones_url":"https://api.github.com/repos/namely/connect/milestones{/number}","notifications_url":"https://api.github.com/repos/namely/connect/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/namely/connect/labels{/name}","releases_url":"https://api.github.com/repos/namely/connect/releases{/id}","created_at":"2014-11-03T03:10:16Z","updated_at":"2015-06-16T14:13:51Z","pushed_at":"2015-07-27T14:20:28Z","git_url":"git://github.com/namely/connect.git","ssh_url":"git@github.com:namely/connect.git","clone_url":"https://github.com/namely/connect.git","svn_url":"https://github.com/namely/connect","homepage":"","size":4621,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":2,"forks":4,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"namely:master","ref":"master","sha":"23717adbfaea478816b382af9c95ae23a3c39337","user":{"login":"namely","id":1004321,"avatar_url":"https://avatars.githubusercontent.com/u/1004321?v=3","gravatar_id":"","url":"https://api.github.com/users/namely","html_url":"https://github.com/namely","followers_url":"https://api.github.com/users/namely/followers","following_url":"https://api.github.com/users/namely/following{/other_user}","gists_url":"https://api.github.com/users/namely/gists{/gist_id}","starred_url":"https://api.github.com/users/namely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/namely/subscriptions","organizations_url":"https://api.github.com/users/namely/orgs","repos_url":"https://api.github.com/users/namely/repos","events_url":"https://api.github.com/users/namely/events{/privacy}","received_events_url":"https://api.github.com/users/namely/received_events","type":"Organization","site_admin":false},"repo":{"id":26101808,"name":"connect","full_name":"namely/connect","owner":{"login":"namely","id":1004321,"avatar_url":"https://avatars.githubusercontent.com/u/1004321?v=3","gravatar_id":"","url":"https://api.github.com/users/namely","html_url":"https://github.com/namely","followers_url":"https://api.github.com/users/namely/followers","following_url":"https://api.github.com/users/namely/following{/other_user}","gists_url":"https://api.github.com/users/namely/gists{/gist_id}","starred_url":"https://api.github.com/users/namely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/namely/subscriptions","organizations_url":"https://api.github.com/users/namely/orgs","repos_url":"https://api.github.com/users/namely/repos","events_url":"https://api.github.com/users/namely/events{/privacy}","received_events_url":"https://api.github.com/users/namely/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/namely/connect","description":"Namely Connect – Integrations with the Namely HRIS System.","fork":false,"url":"https://api.github.com/repos/namely/connect","forks_url":"https://api.github.com/repos/namely/connect/forks","keys_url":"https://api.github.com/repos/namely/connect/keys{/key_id}","collaborators_url":"https://api.github.com/repos/namely/connect/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/namely/connect/teams","hooks_url":"https://api.github.com/repos/namely/connect/hooks","issue_events_url":"https://api.github.com/repos/namely/connect/issues/events{/number}","events_url":"https://api.github.com/repos/namely/connect/events","assignees_url":"https://api.github.com/repos/namely/connect/assignees{/user}","branches_url":"https://api.github.com/repos/namely/connect/branches{/branch}","tags_url":"https://api.github.com/repos/namely/connect/tags","blobs_url":"https://api.github.com/repos/namely/connect/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/namely/connect/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/namely/connect/git/refs{/sha}","trees_url":"https://api.github.com/repos/namely/connect/git/trees{/sha}","statuses_url":"https://api.github.com/repos/namely/connect/statuses/{sha}","languages_url":"https://api.github.com/repos/namely/connect/languages","stargazers_url":"https://api.github.com/repos/namely/connect/stargazers","contributors_url":"https://api.github.com/repos/namely/connect/contributors","subscribers_url":"https://api.github.com/repos/namely/connect/subscribers","subscription_url":"https://api.github.com/repos/namely/connect/subscription","commits_url":"https://api.github.com/repos/namely/connect/commits{/sha}","git_commits_url":"https://api.github.com/repos/namely/connect/git/commits{/sha}","comments_url":"https://api.github.com/repos/namely/connect/comments{/number}","issue_comment_url":"https://api.github.com/repos/namely/connect/issues/comments{/number}","contents_url":"https://api.github.com/repos/namely/connect/contents/{+path}","compare_url":"https://api.github.com/repos/namely/connect/compare/{base}...{head}","merges_url":"https://api.github.com/repos/namely/connect/merges","archive_url":"https://api.github.com/repos/namely/connect/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/namely/connect/downloads","issues_url":"https://api.github.com/repos/namely/connect/issues{/number}","pulls_url":"https://api.github.com/repos/namely/connect/pulls{/number}","milestones_url":"https://api.github.com/repos/namely/connect/milestones{/number}","notifications_url":"https://api.github.com/repos/namely/connect/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/namely/connect/labels{/name}","releases_url":"https://api.github.com/repos/namely/connect/releases{/id}","created_at":"2014-11-03T03:10:16Z","updated_at":"2015-06-16T14:13:51Z","pushed_at":"2015-07-27T14:20:28Z","git_url":"git://github.com/namely/connect.git","ssh_url":"git@github.com:namely/connect.git","clone_url":"https://github.com/namely/connect.git","svn_url":"https://github.com/namely/connect","homepage":"","size":4621,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":2,"forks":4,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/namely/connect/pulls/148"},"html":{"href":"https://github.com/namely/connect/pull/148"},"issue":{"href":"https://api.github.com/repos/namely/connect/issues/148"},"comments":{"href":"https://api.github.com/repos/namely/connect/issues/148/comments"},"review_comments":{"href":"https://api.github.com/repos/namely/connect/pulls/148/comments"},"review_comment":{"href":"https://api.github.com/repos/namely/connect/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/namely/connect/pulls/148/commits"},"statuses":{"href":"https://api.github.com/repos/namely/connect/statuses/2a9e9c323b9b4aa6a268f1ed4e3ce061d3b30d47"}}}}